home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / fd2pragma / source / fd2pragma.c next >
Text File  |  2000-02-28  |  192KB  |  6,688 lines

  1. #define NAME     "FD2Pragma"
  2. #define VERSION  "2"
  3. #define REVISION "100"
  4. #define DATE     "17.02.2000"
  5. //#define DEBUG
  6. //#define DEBUG_OLD
  7.  
  8. /* Programmheader
  9.  
  10.         Name:           FD2Pragma
  11.         Author:         SDI
  12.         Distribution:   PD
  13.         Description:    creates pragmas files, lvo files and stub functions
  14.         Compileropts:   -
  15.         Linkeropts:     -gd -l amiga
  16.  
  17.  1.2    : added pragmas for the Dice compiler. Available via switch "Dice".
  18.         added switches "Aztec", "SAS" and "Maxon": Maxon and Aztec just
  19.         turn on the default (except that Maxon expects pragma files to be
  20.         called "xxx_pragmas.h" instead of "xxx_lib.h"), SAS is equal to
  21.         Dice, except that SAS supports the pragma tagcall.
  22.  2.0    : Added support for tag functions. See the docs for details.
  23.         Author until this version:
  24.         Jochen Wiedmann
  25.         Am Eisteich 9
  26.         72555 Metzingen (Germany)
  27.         Tel. 07123 / 14881
  28.  2.1   19.08.96 : now made by SDI, added correct __MAXON__ support and
  29.         support for StormC++, added auto recognition of tagcall functions
  30.         changed the CLI interface completely
  31.  2.2   21.08.96 : fixed a lot of errors, added debug code
  32.  2.3   22.08.96 : little changes
  33.  2.4   24.08.96 : added proto-file creation
  34.  2.5   25.08.96 : added syscall and fix for functions ending in ...DMA
  35.  2.6   26.08.96 : fixed some errors, added CLIB parameter (used later for
  36.         CSTUBS)
  37.  2.7   01.09.96 : added correct Storm definition, added CLIB scan
  38.  2.8   02.09.96 : added assembler stub functions, added first ASM-stub code
  39.  2.9   04.09.96 : added Comment-Support
  40.  2.10  05.09.96 : changed CSTUB creation a bit
  41.  2.11  07.09.96 : speeded up output, reduced number of strndup calls
  42.  2.12  26.09.96 : pressing CTRL-C in early startup brought a wrong error
  43.         message - fixed
  44.  2.13  30.09.96 : made RegNames field to RegNames string - shorter Exe-file
  45.  2.14  01.10.96 : made SPECIAL 6 default, COMMENT also in LVO files
  46.  2.15  13.10.96 : corrected an error text
  47.  2.16  14.10.96 : added correct comment support and PRIVATE option
  48.  2.17  19.10.96 : now Maxon-compiled in Small data mode
  49.  2.18  22.10.96 : removed EXTERNC in Storm, Maxon and all pragmas, corrected
  50.         the texts, again SAS compiled
  51.  2.19  26.10.96 : added option to create FD files out of pragma files,
  52.         reworked a lot in the source
  53.  2.20  27.10.96 : fixed errors of previous version
  54.  2.21  28.10.96 : fixed error in CLIB scan
  55.  2.22  27.11.96 : SPECIAL numbers for lib and ASM code were wrong, removed
  56.         bug in Tag function stubs
  57.  2.23  06.12.96 : lib and stub creation still was wrong
  58.  2.24  31.12.96 : formed stub libs matching C++ file names, corrected CLIB
  59.         scan errors
  60.  2.25  04.01.97 : added HEADER option (I was asked for)
  61.  2.26  05.01.97 : added HEADER scan (in old file) and auto inserting
  62.  2.27  10.01.97 : stub functions missed register saving, outfuncs skip now,
  63.         when error occured (makes lots of error checking obsolete)
  64.  2.28  11.01.97 : forgot to add offset made by register saving
  65.  2.29  18.01.97 : now libtags and amitags defines only, when at least 1
  66.         tagfunc
  67.  2.30  13.02.97 : added local library base functions, rearranged SPECIAL
  68.         options, fixed some bugs
  69.  2.31  15.02.97 : corrected bugs inserted in previous version
  70.  2.32  16.02.97 : and again bug fixes, still didn't work
  71.  2.33  18.02.97 : corrected texts, added SPECIAL 28
  72.  2.34  25.03.97 : corrected Pragma --> FD file conversion, added ##shadow
  73.  2.35  26.03.97 : added STORMFD option, COMMENT, PRIVATE work again
  74.  2.36  29.03.97 : corrected *tagcall scan a bit
  75.  2.37  20.06.97 : added PASCAL stub lib production (SPECIAL 14, 15)
  76.  2.38  01.07.97 : fixed ##end handling
  77.  2.39  20.07.97 : added better proto file (__GNUC__ inline and pragma call),
  78.         removed C++ comments
  79.  2.40  24.11.97 : added new basenames to the list (devices and resources),
  80.         added tag-exception name checking (dos, utility libraries)
  81.  2.41  27.11.97 : fixed little bug with private functions, CSTUBS now
  82.         special option and no longer commandline arg, SPECIAL 10-15 got
  83.         numbers 11-16 (Sorry)
  84.  2.42  28.11.97 : Added two new warnings for CLIB
  85.  2.43  12.12.97 : faster FD file scan, one new warning
  86.  2.44  19.12.97 : fixed MODE settings for SPECIAL 15,16
  87.  2.45  30.01.98 : added function recognition, included inline creation,
  88.         inline stuff is based on fd2inline 1.11 (incomplete)
  89.  2.46  31.01.98 : continued inline stuff, fixed clib functions
  90.  2.47  05.02.98 : completed inline stuff, added alias names for dos functions
  91.  2.48  06.02.98 : changed Func interface - flags instead of tagmode
  92.  2.49  10.02.98 : fixed inline generation a bit, added SORTED argument,
  93.         RegNames got strings again
  94.  2.50  11.02.98 : bug-fixes, still did not work completely, hopefully got
  95.         all now
  96.  2.51  12.02.98 : and bug-fixes again :-(
  97.  2.52  15.02.98 : changed sorting order of arguments
  98.  2.53  20.02.98 : some code style changes
  99.  2.54  25.02.98 : added SMALLDATA model, removed 5 global variables (better
  100.         style), stub libs use MOVEM when possible, own MemRemember function
  101.  2.55  26.02.98 : bug fixes
  102.  2.56  15.03.98 : added FPU support
  103.  2.57  17.03.98 : added NOFPU keyword
  104.  2.58  19.03.98 : little fixes
  105.  2.59  20.03.98 : added enum and external type definitions defines
  106.  2.60  22.03.98 : added external types file scan
  107.  2.61  23.03.98 : fixed SAS flibcall, added FPU stubs
  108.  2.62  28.03.98 : bug fix with NOFPU and new option FPUONLY, total new clib
  109.         handling
  110.  2.63  29.03.98 : really lots of bug fixes, There are so much problems.
  111.         A better definition format would have been wonderful.
  112.  2.64  05.04.98 : bug fixes
  113.  2.65  07.04.98 : fixed Enforcer hit
  114.  2.66  08.04.98 : bug fix with type detection
  115.  2.67  20.04.98 : added GNU-only stuff
  116.  2.68  28.04.98 : SPECIAL 8 defaults to SAS-C names now
  117.  2.69  25.05.98 : added PowerUP stuff support
  118.  2.70  28.05.98 : added SAS PowerUP stuff, fixed error with function
  119.         detection in CLIB scan
  120.  2.71  30.05.98 : added PowerUP Inlines
  121.  2.72  12.06.98 : sorting turns of COMMENT now
  122.  2.73  05.07.98 : added first FPC stuff, added HEADER to PowerUP stuff,
  123.         added PASCAL header scan
  124.  2.74  06.07.98 : finished FPC stuff
  125.  2.75  07.07.98 : bug fixes for FPC stuff
  126.  2.76  09.07.98 : style changes for FPC stuff, bug fixes
  127.  2.77  11.07.98 : hopefully last FPC bug removed
  128.  2.78  23.07.98 : style changes and bug fixes for FPC stuff, more comments
  129.  2.79  10.08.98 : bug fix, when TO was used with a directory, clib got
  130.         wrong path if it was a relative path description
  131.  2.80  16.08.98 : now prints better error when filopen failed
  132.  2.81  26.10.98 : added BMAP files for BASIC, CODE needs to use large mode
  133.         now :-(
  134.  2.82  28.10.98 : optimizations and bug fixes
  135.  2.83  31.12.98 : fixed powerup stuff a bit
  136.  2.84  05.01.99 : fixed bug in Lib creation, when Dx/Ax and FPx were mixed
  137.  2.85  06.01.99 : added recognition of names ending in MESA, added notagcall
  138.         comment support, void functions no longer can be tagcall
  139.  2.86  10.01.99 : added BGUI special funcs, fixed bug in SPECIAL 42 code
  140.  2.87  12.01.99 : added asm-text (SECTION), moved 12-17 to 13-18
  141.  2.88  17.01.99 : better type detection, added some more basenames, some
  142.         little bug fixes, new makefile reduces file size a lot
  143.  2.89  17.07.99 : added union support
  144.  2.90  12.11.99 : added new motorola syntax, opt040 and vbcc inlines
  145.  2.91  13.11.99 : Now supports changes in OS3.5 includes, why the hell must
  146.         such changes be? I thought new includes will bring cleanup and not
  147.         cleandown. And the reported bugs are still unfixed, but there are
  148.         new ones!, bug-fixes
  149.  2.92  14.11.99 : added PPC-WOS library text and code, FD-creation moved from
  150.     80 to 200 (now finally! - there should be enough free number space),
  151.     added VBCC-PUP text generation
  152.  2.93  15.11.99 : added CheckError function, moved DisplayInfoHandle to
  153.     types definition file
  154.  2.94  16.11.99 : added first VBCC-PowerUP-Lib production stuff, only ELF
  155.     tables missing
  156.  2.95  17.11.99 : finished PowerUP stub stuff, startet PPC-ABI stuff
  157.  2.96  18.11.99 : little bug fixes
  158.  2.97  19.11.99 : added SECTION keyword, moved 11-18 to 12-17, ahh 3 releases
  159.     more and we get an anniversary, my first program using third revision
  160.     digit :-)
  161.  2.98  20.11.99 : added VBCC-WOS-Code for PPC libs
  162.  2.99  25.11.99 : bug fixes
  163.  2.100 17.02.00 : fixed bug for VBCC inlines
  164. */
  165.  
  166. /* A short note, how FD2Pragma works.
  167. Working mode for SPECIAL 200 is a bit different!
  168. The main function parses arguments. Switches are converted into FLAG_XXX values
  169. and stored in global "Flags" variable. SPECIAL numbers are parsed and are used
  170. to call a CreateXXX function, with its interface depending on the need of
  171. arguments (Some have 2, some none, ...). Before SPECIAL arguments are parsed,
  172. FD2Pragma loads FD file and scans it using ScanFDFile(). If SORTED is specified,
  173. the list gets sorted directly afterwards. IF CLIB argument is given, the clib
  174. file is scanned before FD file and a clib list is created. Now SPECIAL is parsed
  175. and mode is set to any of the MODUS_XXX values. Also the destination file name
  176. is created if not given. The destination file is opened now. The mode variable
  177. is used to determine the correct CreatXXX function, which is called afterwards.
  178. This function produces file headers and stuff like that and calls CallFunc to
  179. process each FD entry. CallFunc gets 3 arguments. First the workmode (TAG,
  180. NORMAL, BOTH). Second the comment method (for C it is "/%s *.\n" [. means /],
  181. for ASM it is "\n%s", no comment is reached with 0 argument). The last is most
  182. important. It is the function pointer to a function creating the entries.
  183. These functions have always the same interface and are called through CallFunc
  184. only! They create an entry for the specified function (e.g. FD entry).
  185. Parsing special functions, adding comments, checking for tag-functions, ...
  186. is done by CallFunc. It is no problem to call CallFunc multiple with different
  187. function pointers (as is done for SPECIAL 6 pragmas).
  188.  
  189. The functions can use DoOutput to output texts in printf style or DoOutputDirect
  190. to output all data in fwrite style. Buffering is done automatically.
  191.  
  192. FD2Pragma has its own memory managment. All memory must be allocated using
  193. AllocListMem and is freed automatically. This is especially useful for DupString
  194. function, which is used in FD in CLIB scanner.
  195.  
  196. Normally this source-file is to big and should be splitted in different files
  197. compiled alone and linked together. :-)
  198. */
  199.  
  200. #include <proto/exec.h>
  201. #include <proto/dos.h>
  202.  
  203. #include <exec/memory.h>
  204. #include <exec/execbase.h>
  205. #include <dos/doshunks.h>
  206.  
  207. #define SDI_TO_ANSI
  208. #include "SDI_ASM_STD_protos.h"
  209. #include "SDI_defines.h"
  210. #include "SDI_compiler.h"
  211.  
  212. #ifdef __MAXON__        /* needed for -gd option */
  213.   #include <linkerfunc.h>
  214. #endif
  215.  
  216. #define TEXT_SAS        "__SASC"        /* verified     */
  217. #define TEXT_SAS_60     "__SASC_60"     /* verified     */
  218. #define TEXT_MAXON      "__MAXON__"     /* verified     */
  219. #define TEXT_STORM      "__STORM__"     /* verified     */
  220. #define TEXT_DICE       "_DCC"          /* in 2.0 code  */
  221. #define TEXT_AZTEC      "AZTEC_C"       /* verified     */
  222. #define TEXT_GNUC       "__GNUC__"      /* verified     */
  223.  
  224. #define TEMPSIZE    1024
  225.  
  226. #define FLAG_EXTERNC    (1<< 0) /* add externc statements */
  227. #define FLAG_SYSCALL    (1<< 1) /* create SAS-C syscall pragmas */
  228. #define FLAG_DOCOMMENT  (1<< 2) /* do comment processing */
  229. #define FLAG_PRIVATE    (1<< 3) /* also use private functions */
  230. #define FLAG_LOCALREG   (1<< 4) /* local file uses register call */
  231. #define FLAG_STORMFD    (1<< 5) /* FD file uses strange Storm format */
  232. #define FLAG_PASCAL     (1<< 6) /* library creation with PASCAL style */
  233. #define FLAG_SMALLDATA  (1<< 7) /* libraries use small data modell */
  234. #define FLAG_DONE       (1<< 8) /* destination file is not empty */
  235. #define FLAG_INLINENEW  (1<< 9) /* produce new style inlines */
  236. #define FLAG_INLINESTUB (1<<10) /* produce stubs style inlines */
  237. #define FLAG_NOFPU      (1<<11) /* do not allow FPU registers */
  238. #define FLAG_DIDERROR   (1<<12) /* one error already printed, don't print 2nd */
  239. #define FLAG_FPUONLY    (1<<13) /* only use FPU registers */
  240. #define FLAG_GNUPRAG    (1<<14) /* insert inline call into pragma file */
  241. #define FLAG_POWERUP    (1<<15) /* create Phase5 PowerUP files */
  242. #define FLAG_ASMSECTION (1<<16) /* create SECTIONS in Asm code */
  243. #define FLAG_NEWSYNTAX  (1<<17) /* new motorola syntax */
  244. #define FLAG_NOMOVEM    (1<<18) /* 68040 optimization, don't use MOVEM */
  245. #define FLAG_WOSLIBBASE (1<<19) /* first arg is libbase for VBCC WOS */
  246. #define FLAG_NOPPC    (1<<20)    /* do not allow PPC functions */
  247. #define FLAG_PPCONLY    (1<<21) /* only take PPC functions */
  248. #define FLAG_NOSYMBOL    (1<<23) /* do not create symbol section for libs */
  249.  
  250. #define FUNCFLAG_NORMAL (1<<29) /* normal function */
  251. #define FUNCFLAG_TAG    (1<<30) /* a tagcall function */
  252. #define FUNCFLAG_ALIAS  (1<<31) /* an alias name for previous function */
  253.  
  254. /* Different modes the main program uses, one for each different file
  255.    type (except for those done with one function and flag settings). */
  256. #define MODUS_STUBTEXT           1
  257. #define MODUS_STUBCODE           2
  258. #define MODUS_LOCALDATA          3
  259. #define MODUS_PRAGMA             4
  260. #define MODUS_CSTUB              5
  261. #define MODUS_SASPOWER           6
  262. #define MODUS_PROTOPOWER         7
  263. #define MODUS_BMAP               8
  264. #define MODUS_PASCAL             9
  265. #define MODUS_VBCCINLINE        10
  266. #define MODUS_VBCCPUPLIB    11
  267. #define MODUS_LVOLIB        12
  268. #define MODUS_LVO               50    /* and 51 and 52 and 53   */
  269. #define MODUS_PROTO             60    /* and 61 to 67           */
  270. #define MODUS_INLINE            70    /* and 71 and 72          */
  271. #define MODUS_VBCC              80    /* and 81 to 84           */
  272. #define MODUS_ERROR             100
  273.  
  274. #define ABI_M68K        1
  275. #define ABI_PPC            2
  276. #define ABI_PPC2        3
  277. #define ABI_PPC0        4
  278.  
  279. /* call types for CallFunc */
  280. #define TAGMODE_NORMAL  0    /* produce normal functions only */
  281. #define TAGMODE_TAGS    1    /* produce only tag functions */
  282. #define TAGMODE_BOTH    2    /* produce both types */
  283.  
  284. /* types specifying name method for pragma creation */
  285. #define PRAGMODE_PRAGLIB        1
  286. #define PRAGMODE_PRAGSLIB       2
  287. #define PRAGMODE_PRAGSPRAGS     3
  288. #define PRAGMODE_NONE           4
  289.  
  290. #define BIAS_OFFSET     6  /* value to switch from one to next function */
  291.  
  292. #define EXTTYPESFILE    "FD2Pragma.types"
  293. #define EXTTYPESFILE2   "PROGDIR:FD2Pragma.types"
  294. #define FDFILEEXTENSION "_lib.fd"
  295.  
  296. #define PARAM   "FROM=INFILE/A,SPECIAL/N,MODE/N,"                       \
  297.                 "TO/K,CLIB/K,HEADER/K,"                                 \
  298.                 "AMICALL/K,LIBCALL/K,AMITAGS/K,LIBTAGS/K,"              \
  299.                 "COMMENT/S,EXTERNC/S,FPUONLY/S,NEWSYNTAX/S,NOFPU/S,"    \
  300.                 "NOPPC/S,NOSYMBOL/S,OPT040/S,PPCONLY/S,PRIVATE/S,"    \
  301.                 "SECTION/S,SMALLDATA/S,SORTED/S,STORMFD/S,USESYSCALL/S"
  302.  
  303. const STRPTR RegNames[] = {
  304. "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  305. "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
  306. "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6", "fp7",
  307. };
  308.  
  309. const STRPTR RegNamesUpper[] = {
  310. "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
  311. "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
  312. "FP0", "FP1", "FP2", "FP3", "FP4", "FP5", "FP6", "FP7",
  313. };
  314.  
  315. enum Register_ID {
  316. REG_D0, REG_D1, REG_D2, REG_D3, REG_D4, REG_D5, REG_D6, REG_D7,
  317. REG_A0, REG_A1, REG_A2, REG_A3, REG_A4, REG_A5, REG_A6, REG_A7,
  318. REG_FP0, REG_FP1, REG_FP2, REG_FP3, REG_FP4, REG_FP5, REG_FP6, REG_FP7,
  319. };
  320. #define MAXREGPPC    26
  321. #define MAXREG        24 /* maximum registers of 68K */
  322. #define MAXREGNF        16 /* maximum register number without float regs */
  323.  
  324. struct Args
  325. {
  326.   STRPTR INFILE;
  327.   ULONG* SPECIAL;
  328.   ULONG* MODE;
  329.   STRPTR TO;
  330.   STRPTR CLIB;
  331.   STRPTR HEADER;
  332.   STRPTR AMICALL;
  333.   STRPTR LIBCALL;
  334.   STRPTR AMITAGS;
  335.   STRPTR LIBTAGS;
  336.   ULONG  COMMENT;
  337.   ULONG  EXTERNC;
  338.   ULONG  FPUONLY;
  339.   ULONG  NEWSYNTAX;
  340.   ULONG  NOFPU;
  341.   ULONG  NOPPC;
  342.   ULONG  NOSYMBOL;
  343.   ULONG  OPT040;
  344.   ULONG  PPCONLY;
  345.   ULONG  PRIVATE;
  346.   ULONG  SECTION;
  347.   ULONG  SMALLDATA;
  348.   ULONG  SORTED;
  349.   ULONG  STORMFD;
  350.   ULONG  USESYSCALL;
  351. };
  352.  
  353. struct ShortList {
  354.   struct ShortList    *Next;
  355. };
  356.  
  357. struct ShortListRoot {
  358.   struct ShortList    *First;
  359.   struct ShortList    *Last;
  360.   ULONG                Size;
  361. };
  362.  
  363. #define AMIPRAGFLAG_PUBLIC       (1<< 0) /* is a public function */
  364. #define AMIPRAGFLAG_A6USE        (1<< 1) /* A6 is used for this function */
  365. #define AMIPRAGFLAG_A5USE        (1<< 2) /* A5 is used */
  366. #define AMIPRAGFLAG_A4USE        (1<< 3) /* A4 is used */
  367. #define AMIPRAGFLAG_D7USE        (1<< 4) /* D7 is used */
  368. #define AMIPRAGFLAG_ARGCOUNT     (1<< 5) /* when double args, ... */
  369. #define AMIPRAGFLAG_DIDARGWARN   (1<< 6) /* We printed a argcount warning */
  370. #define AMIPRAGFLAG_FLOATARG     (1<< 7) /* It has a float argument */
  371. #define AMIPRAGFLAG_DIDFLOATWARN (1<< 8) /* We printed a float warning */
  372. #define AMIPRAGFLAG_NOCLIB       (1<< 9) /* No clib definition found */
  373. #define AMIPRAGFLAG_CLIBARGCNT   (1<<10) /* CLIB argument count error */
  374. #define AMIPRAGFLAG_PPC         (1<<11) /* This is an PPC function */
  375. #define AMIPRAGFLAG_DIDPPCWARN     (1<<12) /* we already printed ppc warning */
  376. #define AMIPRAGFLAG_PPC0     (1<<13) /* type PPC0 */
  377. #define AMIPRAGFLAG_PPC2     (1<<14) /* type PPC2 */
  378.  
  379. struct AmiPragma {
  380.   struct ShortList              List;
  381.   UWORD                         Bias;
  382.   UWORD                         Line;
  383.   ULONG                         Flags;
  384.   STRPTR                        FuncName;
  385.   STRPTR                        TagName;
  386.   struct Pragma_AliasName *     AliasName;  /* possible second name */
  387.   UWORD                         NumArgs;  /* register numbers */
  388.   UWORD                         CallArgs; /* argument number in fd file */
  389.   struct AmiArgs
  390.   {
  391.     STRPTR                      ArgName;
  392.     UWORD                       ArgReg;
  393.   } Args[MAXREGPPC];
  394. };
  395.  
  396. struct Comment {
  397.   struct ShortList      List;
  398.   STRPTR                Data;
  399.   UWORD                 Bias;
  400. };
  401.  
  402. struct PragList {
  403.   struct ShortList      List;
  404.   struct ShortListRoot  Data;        /* contains list of PragData */
  405.   STRPTR                Basename;
  406. };
  407.  
  408. struct PragData {
  409.   struct ShortList      List;
  410.   struct ShortListRoot  Name;
  411.   ULONG                 NumNames;
  412.   ULONG                 Bias;
  413.   ULONG                 NumArgs;
  414.   UBYTE                 ArgReg[MAXREG];
  415. };
  416.  
  417. struct FDData {
  418.   STRPTR Name;
  419.   STRPTR Basename;
  420.   ULONG  Bias;
  421.   ULONG  Mode;        /* 0 = Normal, != 0 is TagName */
  422.   ULONG  NumArgs;
  423.   UBYTE  ArgReg[MAXREG];
  424. };
  425.  
  426. /* These CPP types match the strings used for CPP name creation. The
  427. defines are used both for name creation and type specification. */
  428. #define CPP_TYPE_VOID           'v'     /* void,   VOID    */
  429. #define CPP_TYPE_BYTE           'c'     /* char,   BYTE    */
  430. #define CPP_TYPE_WORD           's'     /* short,  WORD    */
  431. #define CPP_TYPE_LONG           'j'     /* long,   LONG    */
  432. #define CPP_TYPE_FLOAT          'f'     /* float,  FLOAT   */
  433. #define CPP_TYPE_DOUBLE         'd'     /* double, DOUBLE  */
  434. #define CPP_TYPE_STRUCTURE      0
  435. #define CPP_TYPE_VARARGS        'e'
  436.  
  437. /* These types are for string creation only. */
  438. #define CPP_TYPE_ENUM           'E'
  439. #define CPP_TYPE_CONST          'C'
  440. #define CPP_TYPE_FUNCTION       'F'
  441. #define CPP_TYPE_POINTER        'P'
  442. #define CPP_TYPE_UNSIGNED       'U'
  443. #define CPP_TYPE_FUNCEND        'p'
  444. #define CPP_TYPE_REGISTER       'r'
  445.  
  446. /* Some flags to be used in CPP_NameType->Flags. */
  447. #define CPP_FLAG_UNSIGNED       (1<<0) /* is an unsigned variable */
  448. #define CPP_FLAG_CONST          (1<<1) /* type is const */
  449. #define CPP_FLAG_STRPTR         (1<<2) /* this variable contains a STRPTR */
  450. #define CPP_FLAG_POINTER        (1<<3) /* the variable is a pointer */
  451. #define CPP_FLAG_ENUM           (1<<4) /* it is a enumeration */
  452. #define CPP_FLAG_STRUCT         (1<<5) /* it is a structure */
  453. #define CPP_FLAG_UNION          (1<<6) /* it is a union */
  454. #define CPP_FLAG_FUNCTION       (1<<7) /* it is a function */
  455. #define CPP_FLAG_BOOLEAN        (1<<8) /* in truth this element is bool */
  456. /* STRPTR is defined different under C and CPP -> I have to create two
  457. names, one time unsigned char *, one time signed char *, when somewhere
  458. a STRPTR occurs */
  459.  
  460. struct CPP_NameType { /* structure to describe a argument type */
  461.   STRPTR StructureName;   /* if a structure or enum only                */
  462.   STRPTR FuncArgs;        /* arguments of function - unterminated       */
  463.   STRPTR TypeStart;       /* start of this type                         */
  464.   UWORD  StructureLength; /* length of the structure name               */
  465.   UWORD  ArgsLength;      /* length of FuncArgs                         */
  466.   UWORD  TypeLength;      /* length of this type                        */
  467.   UWORD  FullLength;      /* length of complete type                    */
  468.   UWORD  PointerDepth;    /* number of * in type                        */
  469.   UWORD  Flags;           /* see above flags                            */
  470.   UBYTE  Type;            /* see above defines                          */
  471. };
  472.  
  473. struct ClibData { /* structure to describe data in CLIB file */
  474.   struct ClibData *     Next;         /* The next entry in this list */
  475.   STRPTR                FuncName;     /* name of the function */
  476.   ULONG                 NumArgs;      /* number of arguments */
  477.   struct CPP_NameType   ReturnType;   /* data for return type */
  478.   struct CPP_NameType   Args[MAXREGPPC+1]; /* data for argument types */
  479. };
  480.  
  481. struct CPP_ExternNames { /* structure for EXTTYPESFILE data */
  482.   struct CPP_ExternNames * Next;        /* The next entry in this list */
  483.   STRPTR                   Type;        /* The unknown type */
  484.   struct CPP_NameType      NameType;    /* The replacement */
  485. };
  486.  
  487. struct CPP_TypeField { /* structure for internal defined types */
  488.   STRPTR Text;          /* name of the type */ 
  489.   UWORD  Length;        /* length of the name string */
  490.   UWORD  Flags;         /* CPP_FLAG flags */
  491.   UBYTE  Type;          /* CPP_TYPE value */
  492. };
  493.  
  494. struct Proto_LibType { /* structure to define structure type of base vars */
  495.   STRPTR BaseName;      /* name of the library base */
  496.   STRPTR StructureName; /* name of the structure to be used */
  497. };
  498.  
  499. struct Pragma_ExecpName { /* structure to specify special tagnames */
  500.   STRPTR FunctionName;  /* function name */
  501.   STRPTR TagName;       /* tag name to be used for this function */
  502. }; /* TagName 0 is valid as well to disable tagfunctions */
  503.  
  504. struct Pragma_AliasName {
  505.   STRPTR FunctionName;
  506.   STRPTR AliasName;
  507.   ULONG  Type;
  508. };
  509.  
  510. #define NTP_NORMAL      0    /* no tags/args    */
  511. #define NTP_TAGS        1    /* TagFunction     */
  512. #define NTP_ARGS        2    /* ArgFunction     */
  513. #define NTP_UNKNOWN     3    /* CommentFunction */
  514.  
  515. struct NameList {
  516.   struct ShortList      List;
  517.   ULONG                 Type;    /* set by OptimizeFDData */
  518.   STRPTR                NormName;
  519.   STRPTR                PragName;
  520. };
  521.  
  522. struct InOut {
  523.   ULONG  file;
  524.   STRPTR pos;
  525.   STRPTR buf;
  526.   ULONG  size;
  527. };
  528.  
  529. /* EHF definitions! */
  530. #define HUNK_PPC_CODE   0x4E9
  531. #define HUNK_RELRELOC26 0x4EC
  532. #define EXT_RELREF26    229
  533.  
  534. /* ------------------------------------------------------------------ */
  535. /* A short set of ELF definitions, see pasm sources in vbcc release for an
  536. more complete set of stuff or get elf documentation. These are needed for
  537. VBCCPUPCode function. */
  538. #define ELFCLASS32    1
  539. #define ELFDATA2MSB    2
  540. #define EV_CURRENT    1    /* version information */
  541. #define ET_REL        1    /* type information */
  542. #define EM_POWERPC    20
  543.  
  544. #define SHT_NULL    0    /* inactive */
  545. #define SHT_PROGBITS    1    /* program information */
  546. #define SHT_SYMTAB    2    /* symbol table */
  547. #define SHT_STRTAB    3    /* string table */
  548. #define SHT_RELA    4    /* relocation */
  549.  
  550. #define SHF_ALLOC    0x2    /* needs memory when started */
  551. #define SHF_EXECINSTR    0x4    /* executable instructions */
  552.  
  553. #define EI_NIDENT    16
  554. #define EI_MAG0        0
  555. #define EI_MAG1        1
  556. #define EI_MAG2        2
  557. #define EI_MAG3        3
  558. #define EI_CLASS    4
  559. #define EI_DATA        5
  560. #define EI_VERSION    6
  561.  
  562. #define STB_LOCAL    0
  563. #define STB_GLOBAL    1
  564. #define STT_NOTYPE    0
  565. #define STT_SECTION    3
  566. #define ELF32_ST_INFO(b,t)    (((b)<<4)+((t)&0xf))
  567. #define ELF32_R_INFO(s,t)    (((s)<<8)+(UBYTE)(t))
  568.  
  569. #define R_PPC_ADDR16_LO     4
  570. #define R_PPC_ADDR16_HA  6
  571. #define R_PPC_REL24    10
  572. #define R_PPC_SDAREL16    32
  573.  
  574. struct Elf32_Ehdr {
  575.   UBYTE e_ident[EI_NIDENT];
  576.   UWORD e_type;
  577.   UWORD e_machine;
  578.   ULONG e_version;
  579.   ULONG e_entry;
  580.   ULONG e_phoff;
  581.   ULONG e_shoff;
  582.   ULONG e_flags;
  583.   UWORD e_ehsize;
  584.   UWORD e_phentsize;
  585.   UWORD e_phnum;
  586.   UWORD e_shentsize;
  587.   UWORD e_shnum;
  588.   UWORD e_shstrndx;
  589. };
  590.  
  591. struct Elf32_Shdr {
  592.   ULONG sh_name;
  593.   ULONG sh_type;
  594.   ULONG sh_flags;
  595.   APTR  sh_addr;
  596.   ULONG sh_offset;
  597.   ULONG sh_size;
  598.   ULONG sh_link;
  599.   ULONG sh_info;
  600.   ULONG sh_addralign;
  601.   ULONG sh_entsize;
  602. };
  603.  
  604. struct Elf32_Rela {
  605.   ULONG r_offset;
  606.   ULONG r_info;
  607.   ULONG r_addend;
  608. };
  609.  
  610. struct Elf32_Sym {
  611.   ULONG st_name;
  612.   ULONG st_value;
  613.   ULONG st_size;
  614.   UBYTE st_info;
  615.   UBYTE st_other;
  616.   UWORD st_shndx;
  617. };
  618.  
  619. struct ArHeader {
  620.   UBYTE ar_name[16];             /* name */
  621.   UBYTE ar_time[12];             /* modification time */
  622.   UBYTE ar_uid[6];               /* user id */
  623.   UBYTE ar_gid[6];               /* group id */
  624.   UBYTE ar_mode[8];              /* octal file permissions */
  625.   UBYTE ar_size[10];             /* size in bytes */
  626.   UBYTE ar_fmag[2];              /* consistency check */
  627. };
  628.  
  629. /* ------------------------------------------------------------------ */
  630.  
  631. struct RememberMem { /* structure for selfmade global memory list */
  632.   struct RememberMem *    rm_Next;    /* pointer to next entry */
  633.   ULONG                   rm_Size;    /* entry size */
  634. };
  635.  
  636. struct RDArgs *         rda             = 0;
  637. struct InOut            in              = {0,0,0,0},
  638.                         out             = {0,0,0,5120};
  639. struct ClibData *       clibdata        = 0;
  640. struct FileInfoBlock *  fib             = 0;
  641. struct ShortListRoot    AmiPragma       = {0,0,sizeof(struct AmiPragma)},
  642.                         Comment         = {0,0,sizeof(struct Comment)};
  643. struct RememberMem *    remember        = 0;
  644. APTR            mempool        = 0;
  645. struct CPP_ExternNames *extnames        = 0;
  646. ULONG                   oldfh           = 0;
  647. ULONG                   lock            = 0;
  648. STRPTR                  BaseName        = 0; /* the correct basename */
  649. STRPTR                  ShortBaseName   = 0; /* the filename part of basename without Base */
  650. STRPTR                  ShortBaseNameUpper = 0; /* like ShortBaseName, but upper case */
  651. ULONG                   DosVersion      = 37; /* force OS2.0 */
  652. STRPTR                  HEADER          = 0;
  653. APTR            tempbuf        = 0;
  654. ULONG                   headersize      = 0;
  655. ULONG                   Flags           = 0;
  656. ULONG                   Output_Error    = 1; /* Output error occured when 0 */
  657. ULONG                   tagfuncs        = 0; /* are there some tagfuncs in FD */
  658.  
  659. /* Prototypes for the functions */
  660. STRPTR DupString(STRPTR, ULONG);
  661. STRPTR AllocListMem(ULONG);
  662. STRPTR SkipBlanks(STRPTR);
  663. STRPTR SkipBlanksRet(STRPTR);
  664. STRPTR SkipName(STRPTR);
  665. STRPTR GetBaseType(void);
  666. ULONG  CloseDest(STRPTR);
  667. ULONG  MakeTagFunction(struct AmiPragma *);
  668. void   MakeLines(STRPTR, ULONG);
  669. ULONG  SpecialFuncs(void);
  670. void   SortFDList(void);
  671. ULONG  ScanFDFile(void);
  672. LONG   ScanTypes(STRPTR, ULONG);
  673. void   FindHeader(void);
  674. ULONG  GetRegisterData(struct AmiPragma *);
  675. UWORD  GetFRegisterData(struct AmiPragma *);
  676. ULONG  OutputXDEF(STRPTR, ...);
  677. ULONG  OutputSYMBOL(STRPTR, ...);
  678. UWORD *AsmStackCopy(UWORD *, struct AmiPragma *, ULONG, ULONG);
  679. /* ------------------------------------------------------------------ */
  680. void   DoError(UBYTE, ULONG, ...);
  681. ULONG  CheckError(struct AmiPragma *, ULONG);
  682. ULONG  Out(ULONG);
  683. ULONG  DoOutput(STRPTR, ...);
  684. ULONG  DoOutputDirect(APTR, ULONG);
  685. /* ------------------------------------------------------------------ */
  686. struct ShortList *NewItem(struct ShortListRoot *);
  687. struct ShortList *RemoveItem(struct ShortListRoot *, struct ShortList *);
  688. void              AddItem(struct ShortListRoot *, struct ShortList *);
  689. /* ------------------------------------------------------------------ */
  690. typedef ULONG (*FuncType)(struct AmiPragma *, ULONG, STRPTR);
  691.  
  692. ULONG FuncAMICALL(struct AmiPragma *, ULONG, STRPTR);
  693. ULONG FuncLIBCALL(struct AmiPragma *, ULONG, STRPTR);
  694. ULONG FuncAsmText(struct AmiPragma *, ULONG, STRPTR);
  695. ULONG FuncAsmCode(struct AmiPragma *, ULONG, STRPTR);
  696. ULONG FuncCSTUBS (struct AmiPragma *, ULONG, STRPTR);
  697. ULONG FuncLVOXDEF(struct AmiPragma *, ULONG, STRPTR);
  698. ULONG FuncLVO    (struct AmiPragma *, ULONG, STRPTR);
  699. ULONG FuncLVOLib (struct AmiPragma *, ULONG, STRPTR);
  700. ULONG FuncLocCode(struct AmiPragma *, ULONG, STRPTR);
  701. ULONG FuncLocText(struct AmiPragma *, ULONG, STRPTR);
  702. ULONG FuncInline (struct AmiPragma *, ULONG, STRPTR);
  703. ULONG FuncPowerUP(struct AmiPragma *, ULONG, STRPTR);
  704. ULONG FuncFPCUnit(struct AmiPragma *, ULONG, STRPTR);
  705. ULONG FuncFPCType(struct AmiPragma *, ULONG, STRPTR);
  706. ULONG FuncBMAP   (struct AmiPragma *, ULONG, STRPTR);
  707. ULONG FuncVBCCInline (struct AmiPragma *, ULONG, STRPTR);
  708. ULONG FuncVBCCWOSText(struct AmiPragma *, ULONG, STRPTR);
  709. ULONG FuncVBCCWOSCode(struct AmiPragma *, ULONG, STRPTR);
  710. ULONG FuncVBCCPUPText(struct AmiPragma *, ULONG, STRPTR);
  711. ULONG FuncVBCCPUPCode(struct AmiPragma *, ULONG, STRPTR);
  712. ULONG CallFunc(ULONG, STRPTR, FuncType);
  713. /* ------------------------------------------------------------------ */
  714. LONG   AddClibEntry(STRPTR, STRPTR, ULONG);
  715. LONG   ScanClibFile(STRPTR, STRPTR);
  716. LONG   IsCPPType(struct CPP_NameType *, UBYTE);
  717. LONG   GetCPPType(struct CPP_NameType *, STRPTR);
  718. struct ClibData *GetClibFunc(STRPTR, struct AmiPragma *, ULONG);
  719. LONG   CheckKeyword(STRPTR, STRPTR, LONG);
  720. ULONG  CopyCPPType(STRPTR, ULONG, struct ClibData *, struct AmiArgs *);
  721. ULONG  OutClibType(struct CPP_NameType *, STRPTR);
  722. ULONG  OutPASCALType(struct CPP_NameType *, STRPTR, ULONG);
  723. /* ------------------------------------------------------------------ */
  724. ULONG CallPrag(ULONG, STRPTR, FuncType);
  725. ULONG CreatePragmaFile(STRPTR, STRPTR, STRPTR, STRPTR, ULONG);
  726. ULONG CreateCSTUBSFile(void);
  727. ULONG CreateLVOFile(ULONG);
  728. ULONG CreateAsmStubs(ULONG, ULONG);
  729. ULONG CreateProtoFile(ULONG);
  730. ULONG CreateLocalData(STRPTR, ULONG, STRPTR, ULONG);
  731. ULONG CreateInline(ULONG, ULONG);
  732. ULONG CreateSASPowerUP(ULONG);
  733. ULONG CreateProtoPowerUP(void);
  734. ULONG CreateFPCUnit(void);
  735. ULONG CreateBMAP(void);
  736. ULONG CreateVBCCInline(void);
  737. ULONG CreateVBCC(ULONG, ULONG);
  738. ULONG CreateVBCCPUPCode(ULONG);
  739. /* ------------------------------------------------------------------ */
  740. ULONG GetName(struct NameList *, struct ShortListRoot *, ULONG);
  741. ULONG MakeFD(struct PragList *);
  742. void  OptimizeFDData(struct PragData *);
  743. UBYTE GetHexValue(UBYTE);
  744. UBYTE GetDoubleHexValue(UBYTE *);
  745. ULONG AddFDData(struct ShortListRoot *, struct FDData *);
  746. ULONG GetLibData(struct FDData *);
  747. ULONG GetFlibData(struct FDData *);
  748. ULONG GetAmiData(struct FDData *);
  749. ULONG CreateFDFile(STRPTR);
  750. /* ------------------------------------------------------------------ */
  751. void main(void);
  752. void End(ULONG);
  753.  
  754. enum {
  755. ERR_TAGFUNC_NEEDS_ARGUMENT,
  756. ERR_CANNOT_CONVERT_PRAGMA_TAGCALL,
  757. ERR_TAG_DEF_WITHOUT_PRAGMA,
  758. ERR_BASENAME_DECLARED_TWICE,
  759. ERR_EXPECTED_SLASH_IN_BASENAME,
  760. ERR_EXPECTED_BASENAME,
  761. ERR_EXPECTED_BIAS_VALUE,
  762. ERR_ASSUMING_POSITIVE_BIAS_VALUE,
  763. ERR_MISSING_FUNCTION_NAME,
  764. ERR_EXPECTED_OPEN_BRACKET,
  765. ERR_TO_MUCH_ARGUMENTS,
  766. ERR_EXPECTED_ARGUMENT_NAME,
  767. ERR_EXPECTED_CLOSE_BRACKET,
  768. ERR_EXPECTED_REGISTER_NAME,
  769. ERR_A7_NOT_ALLOWED,
  770. ERR_REGISTER_USED_TWICE,
  771. ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER,
  772. ERR_ASSUMING_BIAS_OF_30,
  773. ERR_EXTRA_CHARACTERS,
  774. ERR_MISSING_BASENAME,
  775. ERR_WRITING_FILE,
  776. ERR_EXPECTED_COMMA,
  777. ERR_DIFFERENT_TO_PREVIOUS,
  778. ERR_UNKNOWN_VARIABLE_TYPE,
  779. ERR_UNKNOWN_ERROR,
  780. ERR_MISSING_END,
  781. ERR_PROTOTYPE_MISSING,
  782. ERR_NOPROTOTYPES_FILE,
  783. ERR_UNKNOWN_DIRECTIVE,
  784. ERR_INLINE_A4_AND_A5,
  785. ERR_INLINE_D7_AND_A45,
  786. ERR_MISSING_SHORTBASENAME,
  787. ERR_USER_ABORT,
  788. ERR_A6_NOT_ALLOWED,
  789. ERR_EMPTY_FILE,
  790. ERR_FLOATARG_NOT_ALLOWED,
  791. ERR_WRONG_TYPES_LINE,
  792. ERR_LONG_DOUBLE,
  793. ERR_CLIB_ARG_COUNT,
  794. ERR_OPEN_FILE,
  795. ERR_A5_NOT_ALLOWED,
  796. ERR_PPC_FUNCTION_NOT_SUPPORTED,
  797. ERR_UNKNOWN_ABI,
  798. };
  799.  
  800. const struct ErrField {
  801.   UBYTE  Type;    /* 0 = Error, 1 = Warning */
  802.   UBYTE  Skip;
  803.   STRPTR Error;
  804. } Errors[] = {
  805. {1, 1, "Tag function must have arguments."},
  806. {1, 1, "Cannot convert pragma name into tag name."},
  807. {1, 1, "Tag definition without preceding Pragma."},
  808. {1, 0, "Basename declared twice."},
  809. {1, 0, "Expected preceding _ in Basename."},
  810. {1, 1, "Expected Basename."},
  811. {1, 0, "Expected Bias value."},
  812. {1, 0, "Assuming positive bias value."},
  813. {1, 1, "Missing function name."},
  814. {1, 1, "Expected '('."},
  815. {1, 1, "Too much arguments."},
  816. {1, 1, "Expected argument name."},
  817. {1, 1, "Expected ')'."},
  818. {1, 1, "Expected register name."},
  819. {1, 1, "A7 not allowed as argument register."},
  820. {1, 1, "Register used twice."},
  821. {1, 0, "Number of arguments != number of registers."},
  822. {1, 0, "Assuming bias of 30."},
  823. {1, 1, "Extra characters."},
  824. {0, 0, "Missing Basename in FD file."},
  825. {0, 0, "Failed to write destination file."},
  826. {1, 1, "Expected ','."},
  827. {0, 1, "Data different to previous given."},
  828. {1, 0, "Unknown type of argument %ld."},
  829. {0, 0, "Unknown problem: program error or corrupt input data."},
  830. {1, 0, "Missing ##end."},
  831. {1, 0, "Prototype for function \"%s\" not found."},
  832. {0, 0, "No prototypes file (CLIB parameter) was specified."},
  833. {1, 1, "Unknown directive '##%s' found."},
  834. {1, 0, "Usage of both A4 and A5 is not supported."},
  835. {1, 0, "Usage of both D7 and A4 or A5 is not supported."},
  836. {0, 0, "Missing Basename in FD file and FD filename."},
  837. {0, 0, "User aborted operation."},
  838. {1, 0, "A6 not allowed as argument register."},
  839. {1, 0, "Empty or partial file deleted."},
  840. {1, 1, "Floating point arguments not allowed."},
  841. {0, 0, "Wrong definition in external type definition file."},
  842. {1, 0, "Cannot determine if FPU argument is double or single."},
  843. {1, 0, "CLIB argument count differs for %s (%ld != %ld)."},
  844. {0, 0, "Could not open file \"%s\"."},
  845. {1, 0, "A5 cannot be used as argument register."},
  846. {1, 0, "Format supports no PPC functions."},
  847. {1, 0, "Unknown ABI '%s' found."},
  848. };
  849.  
  850. const struct CPP_TypeField CPP_Field[] = {
  851. {"long",        4, 0,                   CPP_TYPE_LONG},
  852. {"LONG",        4, 0,                   CPP_TYPE_LONG},
  853. {"BPTR",        4, 0,                   CPP_TYPE_LONG},
  854. {"BSTR",        4, 0,                   CPP_TYPE_LONG},
  855. {"CxObj",       5, 0,                   CPP_TYPE_LONG},
  856. {"CxMsg",       5, 0,                   CPP_TYPE_LONG},
  857. {"ULONG",       5, CPP_FLAG_UNSIGNED,   CPP_TYPE_LONG},
  858. {"LONGBITS",    8, CPP_FLAG_UNSIGNED,   CPP_TYPE_LONG},
  859. {"CPTR",        4, CPP_FLAG_UNSIGNED,   CPP_TYPE_LONG},
  860. {"Tag",         3, CPP_FLAG_UNSIGNED,   CPP_TYPE_LONG},
  861. {"Object",      6, CPP_FLAG_UNSIGNED,   CPP_TYPE_LONG},
  862. {"short",       5, 0,                   CPP_TYPE_WORD},
  863. {"SHORT",       5, 0,                   CPP_TYPE_WORD},
  864. {"COUNT",       5, 0,                   CPP_TYPE_WORD},
  865. {"WORD",        4, 0,                   CPP_TYPE_WORD},
  866. {"USHORT",      6, CPP_FLAG_UNSIGNED,   CPP_TYPE_WORD},
  867. {"UWORD",       5, CPP_FLAG_UNSIGNED,   CPP_TYPE_WORD},
  868. {"UCOUNT",      6, CPP_FLAG_UNSIGNED,   CPP_TYPE_WORD},
  869. {"WORDBITS",    8, CPP_FLAG_UNSIGNED,   CPP_TYPE_WORD},
  870. {"RPTR",        4, CPP_FLAG_UNSIGNED,   CPP_TYPE_WORD},
  871. {"BOOL",        4, CPP_FLAG_BOOLEAN,    CPP_TYPE_WORD},
  872. {"char",        4, 0,                   CPP_TYPE_BYTE},
  873. {"BYTE",        4, 0,                   CPP_TYPE_BYTE},
  874. {"UBYTE",       5, CPP_FLAG_UNSIGNED,   CPP_TYPE_BYTE},
  875. {"TEXT",        4, CPP_FLAG_UNSIGNED,   CPP_TYPE_BYTE},
  876. {"BYTEBITS",    8, CPP_FLAG_UNSIGNED,   CPP_TYPE_BYTE},
  877. {"float",       5, 0,                   CPP_TYPE_FLOAT},
  878. {"FLOAT",       5, 0,                   CPP_TYPE_FLOAT},
  879. {"double",      6, 0,                   CPP_TYPE_DOUBLE},
  880. {"DOUBLE",      6, 0,                   CPP_TYPE_DOUBLE},
  881. {"void",        4, 0,                   CPP_TYPE_VOID},
  882. {"VOID",        4, 0,                   CPP_TYPE_VOID},
  883. {"APTR",        4, CPP_FLAG_POINTER,    CPP_TYPE_VOID},
  884. {"STRPTR",      6, CPP_FLAG_POINTER|CPP_FLAG_STRPTR|CPP_FLAG_UNSIGNED,  CPP_TYPE_BYTE},
  885. {"CONST_STRPTR",12,CPP_FLAG_POINTER|CPP_FLAG_CONST,                     CPP_TYPE_BYTE},
  886. {"ClassID",     7, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED,                  CPP_TYPE_BYTE},
  887. {"PLANEPTR",    8, CPP_FLAG_POINTER|CPP_FLAG_UNSIGNED,                  CPP_TYPE_BYTE},
  888. {0,0,0,0},
  889. };
  890.  
  891. const struct Proto_LibType Proto_LibTypes[] = {
  892. {"DOSBase",                     "DosLibrary"},
  893. {"SysBase",                     "ExecBase"},
  894. {"ExpansionBase",               "ExpansionBase"},
  895. {"GfxBase",                     "GfxBase"},
  896. {"IntuitionBase",               "IntuitionBase"},
  897. {"LocaleBase",                  "LocaleBase"},
  898. {"MathIeeeDoubBasBase",         "MathIEEEBase"},
  899. {"MathIeeeDoubTransBase",       "MathIEEEBase"},
  900. {"MathIeeeSingBasBase",         "MathIEEEBase"},
  901. {"MathIeeeSingTransBase",       "MathIEEEBase"},
  902. {"RealTimeBase",                "RealTimeBase"},
  903. {"RexxSysBase",                 "RxsLib"},
  904. {"UtilityBase",                 "UtilityBase"},
  905. /* resources - The Node entries may be correct, but I don't know it. */
  906. /* {"BattClockBase",            "Node"}, */
  907. /* {"BattMemBase",              "Node"}, */
  908. {"DiskBase",                    "DiskResource"},
  909. /* {"MiscBase",                 "Node"}, */
  910. /* {"PotgoBase",                "Node"}, */
  911. /* devices */
  912. {"ConsoleDevice",               "Device"},
  913. {"InputBase",                   "Device"},
  914. {"RamdriveDevice",              "Device"},
  915. {"TimerBase",                   "Device"},
  916. /* non default Basenames */
  917. {"DatamasterBase",              "DatamasterBase"},
  918. {"PPBase",                      "PPBase"},
  919. {"ReqToolsBase",                "ReqToolsBase"},
  920. {"UnpackBase",                  "UnpackLibrary"},
  921. {"xfdMasterBase",               "xfdMasterBase"},
  922. {"xadMasterBase",               "xadMasterBase"},
  923. {"xvsBase",                     "xvsBase"},
  924. {"GTXBase",                     "GTXBase"},
  925. {"ArpBase",                     "ArpBase"},
  926. {0, 0},
  927. };
  928.  
  929. /* CachePostDMA, CachePreDMA are done by #?DMA check */
  930. const struct Pragma_ExecpName Pragma_ExecpNames[] = {
  931. {"VFWritef",                    "FWritef"},
  932. {"VFPrintf",                    "FPrintf"},
  933. {"VPrintf",                     "Printf"},
  934. {"ReadArgs",                    0},
  935. {"FreeArgs",                    0},
  936. {"CloneTagItems",               0},
  937. {"FindTagItem",                 0},
  938. {"FreeTagItems",                0},
  939. {"GetTagData",                  0},
  940. {"PackBoolTags",                0},
  941. {"PackStructureTags",           0},
  942. {"UnpackStructureTags",         0},
  943. {"BGUI_PackStructureTags",      0},
  944. {"BGUI_UnpackStructureTags",    0},
  945. {0,0},
  946. };
  947.  
  948. /* For double tagcall names (currently only necessary for dos.library and
  949. datatypes.library). Only one alias supported for a function! */
  950. const struct Pragma_AliasName Pragma_AliasNames[] = {
  951. {"AllocDosObject",      "AllocDosObjectTagList",        FUNCFLAG_NORMAL},
  952. {"CreateNewProc",       "CreateNewProcTagList",         FUNCFLAG_NORMAL},
  953. {"NewLoadSeg",          "NewLoadSegTagList",            FUNCFLAG_NORMAL},
  954. {"SystemTagList",       "System",                       FUNCFLAG_NORMAL},
  955. {"RefreshDTObject",     "RefreshDTObjects",             FUNCFLAG_TAG},
  956. {0,0,0},
  957. };
  958.  
  959. /* special names, which get an x before name in BMAP files */
  960. const STRPTR BMAPSpecial[] =
  961. {"abs", "Close", "Exit", "Input", "Open", "Output", "Read", "tan",
  962. "Translate", "Wait", "Write", 0};
  963.  
  964. STRPTR DupString(STRPTR Str, ULONG Len)
  965. {
  966.   STRPTR res;
  967.   if((res = AllocListMem(Len+1)))
  968.   {
  969.     CopyMem(Str, res, Len);
  970.     res[Len] = '\0';
  971.   }
  972.   return res;
  973. }
  974.  
  975. STRPTR AllocListMem(ULONG size)
  976. {
  977.   if(mempool) /* mempool exists only for OS39 and up */
  978.     return (STRPTR) AllocPooled(mempool, size);
  979.   else /* else use linked list */
  980.   {
  981.     struct RememberMem *r;
  982.  
  983.     size += sizeof(struct RememberMem);
  984.  
  985.     if((r = (struct RememberMem *) AllocMem(size, MEMF_ANY|MEMF_CLEAR)))
  986.     {
  987.       r->rm_Next = remember;
  988.       r->rm_Size = size;
  989.       remember = r;
  990.       return ((STRPTR) r)+sizeof(struct RememberMem);
  991.     }
  992.     return 0;
  993.   }
  994. }
  995.  
  996. STRPTR SkipBlanks(STRPTR OldPtr)
  997. {
  998.   while(*OldPtr == ' ' || *OldPtr == '\t')
  999.     ++OldPtr;
  1000.   return OldPtr;
  1001. }
  1002.  
  1003. STRPTR SkipBlanksRet(STRPTR OldPtr)
  1004. {
  1005.   while(*OldPtr == ' ' || *OldPtr == '\t' || *OldPtr == '\n')
  1006.     ++OldPtr;
  1007.   return OldPtr;
  1008. }
  1009.  
  1010. /*
  1011.   This function is used to skip over variable names.
  1012.  
  1013.   Inputs: OldPtr  - pointer to the beginning of a string.
  1014.  
  1015.   Result: Pointer to the first character of the string, that is not one
  1016.     of a-z, A-Z, 0-9 or the underscore.
  1017. */
  1018.  
  1019. STRPTR SkipName(STRPTR OldPtr)
  1020. {
  1021.   while(isalnum(*OldPtr) || *OldPtr == '_')
  1022.     ++OldPtr;
  1023.   return OldPtr;
  1024. }
  1025.  
  1026. STRPTR GetBaseType(void)
  1027. {
  1028.   ULONG i;
  1029.   STRPTR str = "Library";
  1030.  
  1031.   for(i = 0; BaseName && Proto_LibTypes[i].BaseName; ++i)
  1032.   {
  1033.     if(!(strcmp(Proto_LibTypes[i].BaseName, BaseName)))
  1034.     {
  1035.       str = Proto_LibTypes[i].StructureName; break;
  1036.     }
  1037.   }
  1038.   return str;
  1039. }
  1040.  
  1041. ULONG CloseDest(STRPTR name)
  1042. {
  1043.   if(out.file)
  1044.   {
  1045.     Out(out.size);              /* clears Output-Buffer */
  1046.     Close(out.file);
  1047.     out.file = 0;
  1048.  
  1049.     if(!(Flags & FLAG_DONE) || !Output_Error || CTRL_C)
  1050.     {
  1051.       DoError(ERR_EMPTY_FILE, 0);
  1052.       DeleteFile(name); return 0;
  1053.     }
  1054.     Flags &= ~FLAG_DONE;        /* clear the flag */
  1055.   }
  1056.   else
  1057.     return 0;
  1058.   return 1;
  1059. }
  1060.  
  1061. ULONG MakeTagFunction(struct AmiPragma *ap)
  1062. {
  1063.   ULONG len = strlen(ap->FuncName), i=0;
  1064.  
  1065. #ifdef DEBUG_OLD
  1066.   VPrintf("MakeTagFunction:\n", 0);
  1067. #endif
  1068.  
  1069.   if(!ap->NumArgs)
  1070.     return 1;
  1071.  
  1072.   ++tagfuncs;
  1073.  
  1074.   while(Pragma_ExecpNames[i].FunctionName && /* check the exception names */
  1075.   strcmp(ap->FuncName, Pragma_ExecpNames[i].FunctionName))
  1076.     ++i;
  1077.  
  1078.   if(Pragma_ExecpNames[i].FunctionName)
  1079.   {
  1080.     if(!(ap->TagName = Pragma_ExecpNames[i].TagName));
  1081.       --tagfuncs;
  1082.   }
  1083.   else if(ap->FuncName[len-1] == 'A')
  1084.   {
  1085.     if(!strcmp(ap->FuncName+len-3, "DMA") ||
  1086.     !strcmp(ap->FuncName+len-4, "MESA")) /* skip names with DMA or MESA at end */
  1087.     { --tagfuncs; return 1;}
  1088.     if(!(ap->TagName = DupString(ap->FuncName, len-1)))
  1089.       return 0;
  1090.   }
  1091.   else if(!strcmp(ap->FuncName + len-7, "TagList"))
  1092.   {
  1093.     if(!(ap->TagName = DupString(ap->FuncName, len-3)))
  1094.       return 0;
  1095.     ap->TagName[len-4] = 's';
  1096.   }
  1097.   else if(!strcmp(ap->FuncName + len-4, "Args"))
  1098.   {
  1099.     if(!(ap->TagName = DupString(ap->FuncName, len-4)))
  1100.       return 0;
  1101.   }
  1102.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "tags") ||
  1103.   !stricmp(ap->Args[ap->NumArgs-1].ArgName, "taglist"))
  1104.   {
  1105.     if(!(ap->TagName = DupString(ap->FuncName, len+4)))
  1106.       return 0;
  1107.     CopyMem("Tags", ap->TagName + len, 5);
  1108.   }
  1109.   else if(!stricmp(ap->Args[ap->NumArgs-1].ArgName, "args"))
  1110.   {
  1111.     if(!(ap->TagName = DupString(ap->FuncName, len+4)))
  1112.       return 0;
  1113.     CopyMem("Args", ap->TagName + len, 5);
  1114.   }
  1115.   else
  1116.     --tagfuncs; /* not a tagfunction, incrementing was false, undo it */
  1117.  
  1118.   return 1;
  1119. }
  1120.  
  1121. void MakeLines(STRPTR buffer, ULONG size)
  1122. {
  1123.   if(size && buffer)
  1124.   {
  1125.     /* make a real C++ zero string ending line */
  1126.     while(--size)
  1127.     {
  1128.       if(*buffer == '\n')
  1129.         *buffer = '\0';
  1130.       ++buffer;
  1131.     }
  1132.     *buffer = '\0';
  1133.   }
  1134. }
  1135.  
  1136. /* Do any special functions, which cannot be done with other exception
  1137.    stuff - currently only dos.library DoPkt function. */
  1138. ULONG SpecialFuncs(void)
  1139. {
  1140.   struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.Last;
  1141.  
  1142.   if(ap->Bias == 0xF0 && !strcmp("DoPkt", ap->FuncName))
  1143.   {
  1144.     struct AmiPragma *d;
  1145.     ULONG i;
  1146.  
  1147.     for(i = 0; i < 5; ++i)
  1148.     {
  1149.       if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
  1150.         return 0;
  1151.       CopyMem(ap, d, sizeof(struct AmiPragma));
  1152.       d->FuncName = DupString(ap->FuncName, 6);
  1153.       d->FuncName[5] = '0'+i;
  1154.       d->NumArgs = d->CallArgs = i + 2;
  1155.       AddItem(&AmiPragma, (struct ShortList *) d);
  1156.     }
  1157.   }
  1158.   return 1;
  1159. }
  1160.  
  1161. void SortFDList(void)
  1162. {
  1163.   struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.First, *ap2, *ap3;
  1164.   AmiPragma.First = AmiPragma.Last = 0;
  1165.  
  1166.   while(ap)
  1167.   {
  1168.     ap3 = 0;
  1169.     ap2 = (struct AmiPragma *) AmiPragma.First;
  1170.  
  1171.     /* for FD2Inline style we need to use strcmp instead of stricmp here */
  1172.     while(ap2 && stricmp(ap2->FuncName, ap->FuncName) < 0)
  1173.     {
  1174.       ap3 = ap2;
  1175.       ap2 = (struct AmiPragma *) ap2->List.Next;
  1176.     }
  1177.  
  1178.     ap2 = ap;
  1179.     ap = (struct AmiPragma *) ap->List.Next;
  1180.  
  1181.     if(ap3)
  1182.     {
  1183.       ap2->List.Next = (struct ShortList *) ap3->List.Next;
  1184.       ap3->List.Next = (struct ShortList *) ap2;
  1185.     }
  1186.     else
  1187.     {
  1188.       ap2->List.Next = AmiPragma.First;
  1189.       AmiPragma.First = (struct ShortList *) ap2;
  1190.     }
  1191.     if(ap && !ap->List.Next)
  1192.       AmiPragma.Last = (struct ShortList *) ap2;
  1193.   }
  1194. }
  1195.  
  1196. ULONG ScanFDFile(void)
  1197. {
  1198. #ifdef DEBUG_OLD
  1199.   VPrintf("ScanFDFile:\n", 0);
  1200. #endif
  1201.  
  1202.   ULONG _public = 1;
  1203.   LONG bias = -1;
  1204.   ULONG linenum, len;
  1205.   ULONG actcom = 0;
  1206.   ULONG abi = ABI_M68K;
  1207.  
  1208.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  1209.   {
  1210.     if(*in.pos == '*')          /*  Comment   */
  1211.     {
  1212.       STRPTR oldpos = in.pos;
  1213. #ifdef DEBUG_OLD
  1214.   VPrintf("ScanFDFile: found a comment\n", 0);
  1215. #endif
  1216.       in.pos = SkipBlanks(in.pos+1);
  1217.       if(!strnicmp(in.pos, "notagcall", 9))
  1218.       {
  1219.         struct AmiPragma *ap = (struct AmiPragma *) AmiPragma.Last;
  1220.         
  1221.         if(ap->TagName)
  1222.         {
  1223.           --tagfuncs; ap->TagName = 0;
  1224.         }
  1225.         in.pos = SkipBlanks(in.pos + 9);
  1226.       }
  1227.       else if(!strnicmp(in.pos, "tagcall", 7))  /*  Tag to create?  */
  1228.       {
  1229.         struct AmiPragma *prevpragma = (struct AmiPragma *) AmiPragma.Last;
  1230.  
  1231.         in.pos = SkipBlanks(in.pos + 7);
  1232.         if(!prevpragma)
  1233.         {
  1234.           DoError(ERR_TAG_DEF_WITHOUT_PRAGMA, linenum);
  1235.           ++in.pos;
  1236.           continue;
  1237.         }
  1238.  
  1239.         if(!prevpragma->NumArgs)
  1240.         {
  1241.           DoError(ERR_TAGFUNC_NEEDS_ARGUMENT, linenum);
  1242.           ++in.pos;
  1243.           continue;
  1244.         }
  1245.  
  1246.         /* Get the tag functions name. */
  1247.  
  1248.         if(!prevpragma->TagName && (_public || (Flags & FLAG_PRIVATE)))
  1249.           ++tagfuncs;
  1250.  
  1251.         if(*in.pos)
  1252.         {
  1253.           STRPTR oldptr, tptr = prevpragma->TagName;
  1254.         
  1255.           len = strlen(prevpragma->FuncName)+strlen(in.pos)+1;
  1256.           if(!(prevpragma->TagName = DupString(prevpragma->FuncName, len)))
  1257.             return 0;
  1258.  
  1259.           if(*in.pos == '-')
  1260.           {
  1261.             STRPTR removeptr;
  1262.  
  1263.             oldptr = in.pos = SkipBlanks(in.pos+1);
  1264.             in.pos = SkipName(in.pos);
  1265.             if((len = in.pos-oldptr))
  1266.             {
  1267.               removeptr = prevpragma->TagName+strlen(prevpragma->TagName)-len;
  1268.               if(strncmp(removeptr, oldptr, len))
  1269.               {
  1270. #ifdef DEBUG_OLD
  1271.   {
  1272.     struct data {STRPTR a;STRPTR b;ULONG c;} a;
  1273.     a.a = removeptr;
  1274.     a.b = oldptr;
  1275.     a.c = len;
  1276.     VPrintf("ScanFDFile: *tagcall -: %s, %s, %ld\n", &a);
  1277.   }
  1278. #endif
  1279.                 DoError(ERR_CANNOT_CONVERT_PRAGMA_TAGCALL, linenum);
  1280.                 prevpragma->TagName = tptr;
  1281.                 ++in.pos;
  1282.                 continue;
  1283.               }
  1284.  
  1285.               *removeptr = '\0';
  1286.             }
  1287.             in.pos = SkipBlanks(in.pos);
  1288.           }
  1289.           if(*in.pos == '+')
  1290.             in.pos = SkipBlanks(in.pos+1);
  1291.           else
  1292.             *in.pos = toupper(*in.pos);
  1293.  
  1294.           in.pos = SkipName((oldptr = in.pos));
  1295.           len = in.pos-oldptr;
  1296.           if(len)
  1297.           {
  1298.             ULONG a = strlen(prevpragma->TagName);
  1299.             CopyMem(oldptr, prevpragma->TagName+a, len);
  1300.             prevpragma->TagName[a+len] = '\0';
  1301.           }
  1302.         }
  1303.         else if(!prevpragma->TagName)
  1304.         {
  1305.           len = strlen(prevpragma->FuncName);
  1306.           if(!(prevpragma->TagName = DupString(prevpragma->FuncName, len+4)))
  1307.             return 0;
  1308.           CopyMem("Tags", prevpragma->TagName + len, 5);
  1309.         }
  1310.       }
  1311.       else
  1312.       {
  1313.         if(actcom)
  1314.           *(oldpos-1) = '\n';
  1315.         else if(Flags & FLAG_DOCOMMENT)
  1316.         {
  1317.           struct Comment *d;
  1318.           if(!(d = (struct Comment *) NewItem(&Comment)))
  1319.             return 0;
  1320.           d->Bias = bias;
  1321.           d->Data = oldpos;
  1322.           AddItem(&Comment, (struct ShortList *) d);
  1323.           actcom = 1;
  1324.         }
  1325.         while(*in.pos)
  1326.           ++in.pos;
  1327.       }
  1328.     }
  1329.     else if(*in.pos == '#' && in.pos[1] == '#')
  1330.     {
  1331.       in.pos += 2;
  1332.       actcom = 0; /* no Comment */
  1333.  
  1334.       if(!strnicmp(in.pos, "base", 4))
  1335.       {
  1336. #ifdef DEBUG_OLD
  1337.   VPrintf("ScanFDFile: found ##base\n", 0);
  1338. #endif
  1339.         STRPTR oldptr;
  1340.  
  1341.         if(BaseName)
  1342.           DoError(ERR_BASENAME_DECLARED_TWICE, linenum);
  1343.  
  1344.         in.pos = SkipBlanks(in.pos+4);
  1345.         if(*in.pos != '_')
  1346.           DoError(ERR_EXPECTED_SLASH_IN_BASENAME, linenum);
  1347.         else
  1348.           ++in.pos;
  1349.  
  1350.         in.pos = SkipName((oldptr = in.pos));
  1351.         if((len = in.pos-oldptr))
  1352.         {
  1353.           if(!(BaseName = DupString(oldptr, len)))
  1354.             return 0;
  1355.           if(!ShortBaseName && !(ShortBaseName = DupString(BaseName, len-4)))
  1356.             return 0;
  1357.         }
  1358.         else
  1359.           DoError(ERR_EXPECTED_BASENAME, linenum);
  1360.       }
  1361.       else if(!strnicmp(in.pos, "bias", 4))
  1362.       {
  1363. #ifdef DEBUG_OLD
  1364.   VPrintf("ScanFDFile: found ##bias\n", 0);
  1365. #endif
  1366.         STRPTR ptr;
  1367.         LONG newbias;
  1368.  
  1369.         in.pos += 5;
  1370.         newbias = strtol(in.pos, &ptr, 10);
  1371.         if(ptr == in.pos)
  1372.           DoError(ERR_EXPECTED_BIAS_VALUE, linenum);
  1373.         else if(newbias < 0)
  1374.         {
  1375.           DoError(ERR_ASSUMING_POSITIVE_BIAS_VALUE, linenum);
  1376.           bias = -newbias;
  1377.         }
  1378.         else
  1379.           bias = newbias;
  1380.         in.pos = SkipName(in.pos);
  1381.       }
  1382.       else if(!strnicmp(in.pos, "end", 3))
  1383.       {
  1384.         bias = 0; break;
  1385.       }
  1386.       else if(!strnicmp(in.pos, "shadow", 6)) /* introduced by Storm */
  1387.       {
  1388.         in.pos += 6;
  1389.         bias -= BIAS_OFFSET;
  1390.       }
  1391.       else if(!strnicmp(in.pos, "public", 6))
  1392.       {
  1393.         in.pos += 6;
  1394.         _public = 1;
  1395.       }
  1396.       else if(!strnicmp(in.pos, "private", 7))
  1397.       {
  1398.         in.pos += 7;
  1399.         _public = 0;
  1400.       }
  1401.       else if(!strnicmp(in.pos, "abi", 3))
  1402.       {
  1403.         in.pos = SkipBlanks(in.pos+3);
  1404.         if(!strnicmp(in.pos, "M68k", 4))
  1405.         {
  1406.           abi = ABI_M68K; in.pos += 4;
  1407.         }
  1408.         else if(!strnicmp(in.pos, "PPC0", 4))
  1409.         {
  1410.           abi = ABI_PPC0; in.pos += 4;
  1411.         }
  1412.         else if(!strnicmp(in.pos, "PPC2", 4))
  1413.         {
  1414.           abi = ABI_PPC2; in.pos += 4;
  1415.         }
  1416.         else if(!strnicmp(in.pos, "PPC", 3))
  1417.         {
  1418.           abi = ABI_PPC; in.pos += 3;
  1419.         }
  1420.         else
  1421.           DoError(ERR_UNKNOWN_ABI, linenum, in.pos);
  1422.       }
  1423.       else
  1424.         DoError(ERR_UNKNOWN_DIRECTIVE, linenum, in.pos);
  1425.     }
  1426.     else if(abi != ABI_M68K)
  1427.     {
  1428. /*******************************************************/
  1429. #ifdef DEBUG
  1430.   VPrintf("ScanFDFile: scan PPC Function\n", 0);
  1431. #endif
  1432.       STRPTR oldptr;
  1433.       struct AmiPragma ap;
  1434.  
  1435.       memset(&ap, 0, sizeof(struct AmiPragma));
  1436.       actcom = 0;
  1437.  
  1438.       oldptr = in.pos = SkipBlanks(in.pos);
  1439.       in.pos = SkipName(oldptr);
  1440.       if(!(len = in.pos-oldptr))
  1441.       {
  1442.         DoError(ERR_MISSING_FUNCTION_NAME, linenum);
  1443.         ++in.pos;
  1444.         continue;
  1445.       }
  1446.  
  1447.       ap.FuncName = oldptr;
  1448.  
  1449.       in.pos = SkipBlanks(in.pos);
  1450.       if(*in.pos != '('/*)*/)
  1451.       {
  1452.         DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  1453.         ++in.pos;
  1454.         continue;
  1455.       }
  1456.  
  1457.       *in.pos = '\0'; /* create c string of FunctionName */
  1458.  
  1459. #ifdef DEBUG
  1460.   VPrintf("ScanFDFile: found ppc function %s\n", &ap.FuncName);
  1461. #endif
  1462.  
  1463.       do
  1464.       {
  1465.         oldptr = in.pos = SkipBlanks(in.pos+1);
  1466.  
  1467.         if(*in.pos == /*(*/')' && !ap.CallArgs)
  1468.           break;
  1469.  
  1470.         if(ap.CallArgs >= MAXREGPPC)
  1471.         {
  1472.           DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
  1473.         }
  1474.  
  1475.         in.pos = SkipName(oldptr);
  1476.         if(*in.pos == '*')
  1477.           ++in.pos;
  1478.         if(!(len = in.pos-oldptr))
  1479.         {
  1480.           DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
  1481.           break;
  1482.         }
  1483.  
  1484.         ap.Args[ap.CallArgs++].ArgName = oldptr;
  1485.         oldptr = in.pos;
  1486.  
  1487.         in.pos = SkipBlanks(in.pos);
  1488.         if(*in.pos != ',' && *in.pos != '/' && *in.pos != /*(*/')')
  1489.         {
  1490.           DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  1491.           break;
  1492.         }
  1493.         if(*in.pos != /*(*/')') /* create c string ending */
  1494.           *oldptr = '\0';
  1495.       } while(*in.pos != /*(*/')');
  1496.  
  1497.       if(*in.pos != /*(*/')')
  1498.       {
  1499.         while(*(in.pos++))
  1500.           ++in.pos;
  1501.         continue;
  1502.       }
  1503.       else
  1504.         *oldptr = '\0'; /* create c string ending for last argument */
  1505.  
  1506.       if(*(in.pos = SkipBlanks(in.pos+1)) != '('/*)*/)
  1507.       {
  1508.         DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  1509.         ++in.pos;
  1510.         continue;
  1511.       }
  1512.       if(*(in.pos = SkipBlanks(in.pos+1)) != /*(*/')')
  1513.       {
  1514.         DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  1515.         ++in.pos;
  1516.         continue;
  1517.       }
  1518.       ++in.pos;
  1519.  
  1520.       ap.Bias = bias;
  1521.       ap.Line = linenum;
  1522.       ap.NumArgs = ap.CallArgs;
  1523.       bias += BIAS_OFFSET;
  1524.  
  1525.       if(bias == -1)
  1526.       {
  1527.         DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
  1528.         bias = 30;
  1529.       }
  1530.  
  1531.       if(_public)
  1532.         ap.Flags |= AMIPRAGFLAG_PUBLIC;
  1533.       ap.Flags |= AMIPRAGFLAG_PPC;
  1534.       if(abi == ABI_PPC0)
  1535.         ap.Flags |= AMIPRAGFLAG_PPC0;
  1536.       else if(abi == ABI_PPC2)
  1537.         ap.Flags |= AMIPRAGFLAG_PPC2;
  1538.  
  1539.       if((_public || (Flags & FLAG_PRIVATE)) && !MakeTagFunction(&ap))
  1540.         return 0;
  1541.       else      /* check the alias names */
  1542.       {
  1543.         ULONG i = 0;
  1544.  
  1545.         while(Pragma_AliasNames[i].FunctionName &&
  1546.         strcmp(ap.FuncName, Pragma_AliasNames[i].FunctionName) &&
  1547.         strcmp(ap.TagName, Pragma_AliasNames[i].FunctionName))
  1548.           ++i;
  1549.  
  1550.         if(Pragma_AliasNames[i].FunctionName)
  1551.           ap.AliasName = (struct Pragma_AliasName *) &Pragma_AliasNames[i];
  1552.       }
  1553.  
  1554.       if(!(Flags & FLAG_NOPPC))
  1555.       {
  1556.         struct AmiPragma *d;
  1557.         if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
  1558.           return 0;
  1559.         CopyMem(&ap, d, sizeof(struct AmiPragma));
  1560.         AddItem(&AmiPragma, (struct ShortList *) d);
  1561. /*
  1562.         if(!SpecialFuncs())
  1563.           return 0;
  1564. */
  1565.       }
  1566.     }
  1567.     else
  1568.     {
  1569. #ifdef DEBUG_OLD
  1570.   VPrintf("ScanFDFile: scan Function\n", 0);
  1571. #endif
  1572.       STRPTR oldptr;
  1573.       struct AmiPragma ap;
  1574.  
  1575.       memset(&ap, 0, sizeof(struct AmiPragma));
  1576.       actcom = 0;
  1577.  
  1578.       oldptr = in.pos = SkipBlanks(in.pos);
  1579.       in.pos = SkipName(oldptr);
  1580.       if(!(len = in.pos-oldptr))
  1581.       {
  1582.         DoError(ERR_MISSING_FUNCTION_NAME, linenum);
  1583.         ++in.pos;
  1584.         continue;
  1585.       }
  1586.  
  1587.       ap.FuncName = oldptr;
  1588.  
  1589.       in.pos = SkipBlanks(in.pos);
  1590.       if(*in.pos != '('/*)*/)
  1591.       {
  1592.         DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  1593.         ++in.pos;
  1594.         continue;
  1595.       }
  1596.  
  1597.       *in.pos = '\0'; /* create c string of FunctionName */
  1598.  
  1599. #ifdef DEBUG_OLD
  1600.   VPrintf("ScanFDFile: found function %s\n", &ap.FuncName);
  1601. #endif
  1602.  
  1603.       do
  1604.       {
  1605.         oldptr = in.pos = SkipBlanks(in.pos+1);
  1606.  
  1607.         if(*in.pos == /*(*/')' && !ap.CallArgs)
  1608.           break;
  1609.  
  1610.         if(ap.CallArgs >= MAXREG-2)
  1611.         {
  1612.           DoError(ERR_TO_MUCH_ARGUMENTS, linenum); break;
  1613.         }
  1614.  
  1615.         in.pos = SkipName(oldptr);
  1616.         if(*in.pos == '*')
  1617.           ++in.pos;
  1618.         if(!(len = in.pos-oldptr))
  1619.         {
  1620.           DoError(ERR_EXPECTED_ARGUMENT_NAME, linenum);
  1621.           break;
  1622.         }
  1623.  
  1624.         ap.Args[ap.CallArgs++].ArgName = oldptr;
  1625.         oldptr = in.pos;
  1626.  
  1627.         in.pos = SkipBlanks(in.pos);
  1628.         if(*in.pos != ',' && *in.pos != '/' && *in.pos != /*(*/')')
  1629.         {
  1630.           DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  1631.           break;
  1632.         }
  1633.         if(*in.pos != /*(*/')') /* create c string ending */
  1634.           *oldptr = '\0';
  1635.       } while(*in.pos != /*(*/')');
  1636.       if(*in.pos != /*(*/')')
  1637.       {
  1638.         while(*(in.pos++))
  1639.           ++in.pos;
  1640.         continue;
  1641.       }
  1642.       else
  1643.         *oldptr = '\0'; /* create c string ending for last argument */
  1644.  
  1645.       if(*(in.pos = SkipBlanks(in.pos+1)) != '('/*)*/)
  1646.       {
  1647.         DoError(ERR_EXPECTED_OPEN_BRACKET, linenum);
  1648.         ++in.pos;
  1649.         continue;
  1650.       }
  1651.  
  1652.       do
  1653.       {
  1654.         ULONG i;
  1655.  
  1656.         oldptr = in.pos = SkipBlanks(in.pos + 1);
  1657.  
  1658.         if(*in.pos == /*(*/')' && !ap.NumArgs)
  1659.           break;
  1660.  
  1661.         in.pos = SkipName(oldptr);
  1662.         len = in.pos-oldptr;
  1663.  
  1664.         for(i = 0; i < MAXREG; ++i)
  1665.           if(!strnicmp(RegNames[i], oldptr, len))
  1666.             break;
  1667.  
  1668.         if(i == MAXREG)
  1669.         {
  1670.           DoError(ERR_EXPECTED_REGISTER_NAME, linenum);
  1671.           break;
  1672.         }
  1673.         else if(i == REG_A6)
  1674.           ap.Flags |= AMIPRAGFLAG_A6USE;
  1675.         else if(i == REG_A5)
  1676.           ap.Flags |= AMIPRAGFLAG_A5USE;
  1677.         else if(i == REG_A4)
  1678.           ap.Flags |= AMIPRAGFLAG_A4USE;
  1679.         else if(i == REG_D7)
  1680.           ap.Flags |= AMIPRAGFLAG_D7USE;
  1681.         else if(i == REG_A7)
  1682.         {
  1683.           DoError(ERR_A7_NOT_ALLOWED, linenum);
  1684.           break;
  1685.         }
  1686.         else if(i >= REG_FP0)
  1687.           ap.Flags |= AMIPRAGFLAG_FLOATARG;
  1688.  
  1689.         ap.Args[ap.NumArgs].ArgReg = i;
  1690.  
  1691.         if(ap.CallArgs < ap.NumArgs)    /* get name when no given */
  1692.           ap.Args[ap.NumArgs].ArgName = RegNames[i];
  1693.  
  1694.         for(i = 0; i < ap.NumArgs; i++)
  1695.         {
  1696.           if(ap.Args[ap.NumArgs].ArgReg == ap.Args[i].ArgReg)
  1697.           {
  1698.             DoError(ERR_REGISTER_USED_TWICE, linenum);
  1699.             break;
  1700.           }
  1701.         }
  1702.         if(i < ap.NumArgs)
  1703.           break;
  1704.  
  1705.         ++ap.NumArgs;
  1706.  
  1707.         in.pos = SkipBlanks(in.pos);
  1708.         if(*in.pos != ',' && *in.pos != '/' && *in.pos != /*(*/')')
  1709.         {
  1710.           DoError(ERR_EXPECTED_CLOSE_BRACKET, linenum);
  1711.           break;
  1712.         }
  1713.       } while(*in.pos != /*(*/')');
  1714.  
  1715.       ap.Bias = bias;
  1716.       ap.Line = linenum;
  1717.       bias += BIAS_OFFSET;
  1718.  
  1719.       if(*in.pos != /*(*/')')
  1720.       {
  1721.         while(*(in.pos++))
  1722.           ++in.pos;
  1723.         continue;
  1724.       }
  1725.       else
  1726.         ++in.pos;
  1727.  
  1728.       if(Flags & FLAG_STORMFD)
  1729.       {
  1730.         if(!strcmp(ap.Args[ap.CallArgs-1].ArgName, "tags"))
  1731.         {
  1732.           ap.TagName = ap.FuncName;
  1733.           ap.FuncName = 0;
  1734.           ++tagfuncs;
  1735. #ifdef DEBUG_OLD
  1736.   VPrintf("ScanFDFile: StormFD mode, tag func: %s\n", &ap.TagName);
  1737. #endif
  1738.         }
  1739. #ifdef DEBUG_OLD
  1740.   else
  1741.   {
  1742.     STRPTR a[2];
  1743.     a[0] = ap.FuncName;
  1744.     a[1] = ap.Args[ap.CallArgs-1].ArgName;
  1745.     VPrintf("ScanFDFile: StormFD mode, normal func: %s(..., %s)\n", &a);
  1746.   }
  1747. #endif
  1748.       }
  1749.       else if((_public || (Flags & FLAG_PRIVATE)) && !MakeTagFunction(&ap))
  1750.         return 0;
  1751.       else      /* check the alias names */
  1752.       {
  1753.         ULONG i = 0;
  1754.  
  1755.         while(Pragma_AliasNames[i].FunctionName &&
  1756.         strcmp(ap.FuncName, Pragma_AliasNames[i].FunctionName) &&
  1757.         strcmp(ap.TagName, Pragma_AliasNames[i].FunctionName))
  1758.           ++i;
  1759.  
  1760.         if(Pragma_AliasNames[i].FunctionName)
  1761.           ap.AliasName = (struct Pragma_AliasName *) &Pragma_AliasNames[i];
  1762.       }
  1763.  
  1764.       if(ap.CallArgs != ap.NumArgs)
  1765.         ap.Flags |= AMIPRAGFLAG_ARGCOUNT;
  1766.  
  1767.       if(bias == -1)
  1768.       {
  1769.         DoError(ERR_ASSUMING_BIAS_OF_30, linenum);
  1770.         bias = 30;
  1771.       }
  1772.  
  1773.       if(_public)
  1774.         ap.Flags |= AMIPRAGFLAG_PUBLIC;
  1775.  
  1776.       if((Flags & FLAG_NOFPU) && (ap.Flags & AMIPRAGFLAG_FLOATARG))
  1777.         DoError(ERR_FLOATARG_NOT_ALLOWED, linenum);
  1778.       else if(((ap.Flags & AMIPRAGFLAG_FLOATARG) || !(Flags & FLAG_FPUONLY))
  1779.       && !(Flags & FLAG_PPCONLY))
  1780.       { /* skip all without FPU when FPUONLY and PPC when PPCONLY */
  1781.         struct AmiPragma *d;
  1782.         if(!(d = (struct AmiPragma *) NewItem(&AmiPragma)))
  1783.           return 0;
  1784.         CopyMem(&ap, d, sizeof(struct AmiPragma));
  1785.         AddItem(&AmiPragma, (struct ShortList *) d);
  1786.         if(!SpecialFuncs())
  1787.           return 0;
  1788.       }
  1789.     }
  1790.  
  1791.     in.pos = SkipBlanks(in.pos);
  1792.     if(*in.pos)
  1793.       DoError(ERR_EXTRA_CHARACTERS, linenum);
  1794.     ++in.pos; /* skip '\0' */
  1795.   }
  1796.  
  1797.   if(CTRL_C)
  1798.   {
  1799.     DoError(ERR_USER_ABORT, 0);
  1800.     return 0;
  1801.   }
  1802.  
  1803.   if(bias)
  1804.     DoError(ERR_MISSING_END, 0);
  1805.  
  1806.   return 1;
  1807. }
  1808.  
  1809. LONG ScanTypes(STRPTR ptr, ULONG size)
  1810. {
  1811.   struct CPP_ExternNames *a = 0, *b = 0;
  1812.   STRPTR endptr = ptr+size;
  1813.   LONG line;
  1814.  
  1815.   for(line = 1; ptr < endptr; ++line)
  1816.   {
  1817.     struct CPP_ExternNames *n;
  1818.  
  1819.     if(*ptr == '*') /* skip comments */
  1820.     {
  1821.       while(ptr < endptr && *(ptr++) != '\n')
  1822.         ;
  1823.     }
  1824.     else if((n = (struct CPP_ExternNames *)
  1825.       AllocListMem(sizeof(struct CPP_ExternNames))))
  1826.     {
  1827.       STRPTR wptr;
  1828.  
  1829.       n->Type = ptr; /* store start */
  1830.  
  1831.       wptr = ptr;
  1832.       while(ptr < endptr && *ptr != ':' && *ptr != '\n')
  1833.       {
  1834.         if(*ptr == '\t' || *ptr == ' ')
  1835.         {
  1836.           *(wptr++) = ' ';
  1837.           ptr = SkipBlanks(ptr);
  1838.         }
  1839.         else
  1840.           *(wptr++) = *(ptr++);
  1841.       }
  1842.       if(*(ptr++) != ':')
  1843.         return line;
  1844.       if(*(wptr-1) == ' ')
  1845.         --wptr;
  1846.       *wptr = 0;
  1847.       
  1848.       if(!GetCPPType(&n->NameType, (ptr = SkipBlanks(ptr))))
  1849.         return line;
  1850. #ifdef DEBUG_OLD
  1851.   Printf("'%20s', slen %2ld, typelen %2ld, pntd %ld, type %lc, sn '%.3s'\n",
  1852.   n->Type, n->NameType.StructureLength, n->NameType.FullLength,
  1853.   n->NameType.PointerDepth, n->NameType.Type ? n->NameType.Type : 's',
  1854.   n->NameType.StructureName ? n->NameType.StructureName : "<e>");
  1855. #endif
  1856.       ptr = SkipBlanks(n->NameType.TypeStart+n->NameType.FullLength);
  1857.       if(*(ptr++) != '\n')
  1858.       {
  1859. #ifdef DEBUG_OLD
  1860.   Printf("%.30s\n", ptr);
  1861. #endif
  1862.         return line;
  1863.       }
  1864.  
  1865.       if(!a)
  1866.         b = n;
  1867.       else
  1868.         a->Next = n;
  1869.       a = n;
  1870.     }
  1871.     else
  1872.       return -1;
  1873.   }
  1874.   extnames = b; /* now store the list */
  1875.   return 0;
  1876. }
  1877.  
  1878. void FindHeader(void)
  1879. {
  1880.   STRPTR str = HEADER;
  1881.   ULONG mode = 0;
  1882.  
  1883.   do
  1884.   {
  1885.     if(!mode)
  1886.       HEADER = str;
  1887.  
  1888.     if(*str == '/')
  1889.     {
  1890.       ++str;
  1891.       if(*str == '*')
  1892.       {
  1893.         mode = 2; break;
  1894.       }
  1895.       else if(*str == '/')
  1896.         mode = 1;
  1897.     }
  1898.     else if(*str == '*' || *str == ';')
  1899.       mode = 1;
  1900.     else if(*str == '{'/*}*/)
  1901.     {
  1902.       mode = 3; break;
  1903.     }
  1904.     else if(*str == '('/*)*/ && *(++str) == '*')
  1905.     {
  1906.       mode = 4; break;
  1907.     }
  1908.     else if(mode)
  1909.       break;
  1910.     while(*str && *(str++) != '\n')
  1911.       ;
  1912.   } while(*str);
  1913.  
  1914.   if(mode == 2)
  1915.   {
  1916.     while(*str && (*(str-1) != '*' || *str != '/'))
  1917.       ++str;
  1918.     while(*str && *(str++) != '\n')
  1919.       ;
  1920.   }
  1921.   else if(mode == 3)
  1922.   {
  1923.     while(*str && *str != /*{*/'}')
  1924.       ++str;
  1925.     while(*str && *(str++) != '\n')
  1926.       ;
  1927.   }
  1928.   else if(mode == 4)
  1929.   {
  1930.     while(*str && (*(str-1) != '*' || *str != /*(*/')'))
  1931.       ++str;
  1932.     while(*str && *(str++) != '\n')
  1933.       ;
  1934.   }
  1935.  
  1936.   if(mode)
  1937.     headersize = str-HEADER;
  1938.   else
  1939.   {
  1940.     HEADER = 0; headersize = 0;
  1941.   }
  1942. }
  1943.  
  1944. /* returns decrement data in bits 0-15 and increment data in bits 16-31 */
  1945. ULONG GetRegisterData(struct AmiPragma *ap)
  1946. {
  1947. /* usage of result:
  1948.     48E7 <lower word>    MOVEM.L <registers>,-(A7) ; D0 is bit 15
  1949.     4CDF <upper word>    MOVEM.L (A7)+,<registers> ; D0 is bit 0
  1950. */
  1951.   register ULONG i, data = 0, reg;
  1952.  
  1953.   for(i = 0; i < ap->NumArgs; ++i)
  1954.   {
  1955.     if((reg = ap->Args[i].ArgReg) <= REG_FP0)
  1956.     {
  1957.       if(reg >= 10 || (reg >= 2 &&  reg <= 7)) /* A2-A7 and D2-D7 */
  1958.         data |= (1 << (reg + 16)) + (1 << (15 - reg));
  1959.     }
  1960.   }
  1961.   if(data)      /* set A6 only when other register used */
  1962.     data |= 0x40000002;
  1963.   return data;
  1964. }
  1965.  
  1966. UWORD GetFRegisterData(struct AmiPragma *ap)
  1967. {
  1968. /* usage of result:
  1969.     F227 <upper byte>    FMOVEM.X <registers>,-(A7) ; FP0 is bit 0
  1970.     F21F <lower byte>    FMOVEM.X (A7)+,<registers> ; FP0 is bit 7
  1971. */
  1972.   register ULONG i, reg;
  1973.   register UWORD data = 0;
  1974.  
  1975.   for(i = 0; i < ap->NumArgs; ++i)
  1976.   {
  1977.     if((reg = ap->Args[i].ArgReg) >= REG_FP2)
  1978.     {
  1979.       reg -= REG_FP0;
  1980.       data |= (1 << (reg + 8)) + (1 << (7 - reg));
  1981.     }
  1982.   }
  1983.   return data;
  1984. }
  1985.  
  1986. ASM(static void) SAVEDS xdefputfunc(REG(d0, UBYTE data), REG(a3, STRPTR *a))
  1987. {
  1988. #ifdef __MAXON__
  1989.   GetBaseReg();
  1990. #endif
  1991.   *((*a)++) = data;
  1992. }
  1993.  
  1994. ULONG OutputXDEF(STRPTR format, ...)
  1995. {
  1996.   UBYTE b[150];
  1997.   STRPTR c = b + 4;
  1998.   UWORD i;
  1999.  
  2000.   memset(b, 0, 150);
  2001.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  2002.   (void(*)()) xdefputfunc, &c);
  2003.   /* c now holds pointer to end */
  2004.   i = (c-(b+4)+2)>>2;
  2005.   *((ULONG *) b) = 0x01000000 + i;
  2006.  
  2007.   return DoOutputDirect(b, (i+2)<<2);
  2008. }
  2009.  
  2010. ULONG OutputSYMBOL(STRPTR format, ...)
  2011. {
  2012.   UBYTE b[150];
  2013.   STRPTR c = b+4;
  2014.   UWORD i;
  2015.  
  2016.   memset(b, 0, 150);
  2017.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  2018.   (void(*)()) xdefputfunc, &c);
  2019.   /* c now holds pointer to end */
  2020.   i = (c-(b+4)+2)>>2;
  2021.   *((ULONG *) b) = i;
  2022.   return DoOutputDirect(b, (i+2)<<2);
  2023. }
  2024.  
  2025. UWORD *AsmStackCopy(UWORD *data, struct AmiPragma *ap, ULONG flags,
  2026. ULONG ofs)
  2027. {
  2028.   ULONG j, k;
  2029.  
  2030.   if(Flags & FLAG_PASCAL)
  2031.   {
  2032.     k = ap->NumArgs;
  2033.  
  2034.     while(k)
  2035.     {
  2036.       if(ap->Args[k-1].ArgReg >= REG_FP0)
  2037.       {
  2038.         struct ClibData *cd; 
  2039.  
  2040.         cd = GetClibFunc(ap->FuncName, ap, flags);
  2041.         *(data++) = 0xF22F;             /* FMOVE.? offs(A7),FPx */
  2042.  
  2043.         if(cd && IsCPPType(&cd->Args[k-1], CPP_TYPE_DOUBLE))
  2044.         {
  2045.           *(data++) = 0x5400 + ((ap->Args[--k].ArgReg-REG_FP0)<<7);
  2046.           *(data++) = ofs<<2;           /* one double needs two longs */
  2047.           ofs += 2;
  2048.         }
  2049.         else
  2050.         {
  2051.           if(!cd || !IsCPPType(&cd->Args[k-1], CPP_TYPE_FLOAT))
  2052.             DoError(ERR_LONG_DOUBLE, ap->Line);
  2053.           *(data++) = 0x4400 + ((ap->Args[--k].ArgReg-REG_FP0)<<7);
  2054.           *(data++) = (ofs++) << 2;
  2055.         }
  2056.       }
  2057.       else if((k >= 2) && (ap->Args[k-1].ArgReg < ap->Args[k-2].ArgReg)
  2058.       && ap->Args[k-2].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
  2059.       {
  2060.         *(data++) = 0x4CEF;             /* MOVEM.L offs(A7),xxx */
  2061.         *(data++) = 0;
  2062.         *(data++) = ofs << 2;           /* store start offset */
  2063.         do
  2064.         {
  2065.           j = ap->Args[--k].ArgReg;
  2066.  
  2067.           ++ofs;
  2068.           *(data-2) |= 1 << j;
  2069.         } while(k && j < ap->Args[k-1].ArgReg &&
  2070.           ap->Args[k-1].ArgReg < REG_FP0);
  2071.       }
  2072.       else
  2073.       {
  2074.         *data = 0x202F;                 /* MOVE.L offs(A7),xxx */
  2075.  
  2076.         if((j = ap->Args[--k].ArgReg) > 7)
  2077.         {
  2078.           *data |= (1<<6); j -= 8;      /* set MOVEA bit */
  2079.         }
  2080.         *(data++) |= j << 9;            /* set destination register */
  2081.         *(data++) = (ofs++) << 2;
  2082.       }
  2083.     }
  2084.   }
  2085.   else
  2086.   {
  2087.     ULONG i = 0;
  2088.  
  2089.     k = ap->NumArgs - ((flags & FUNCFLAG_TAG) ? 1 : 0);
  2090.  
  2091.     while(i < k)
  2092.     {
  2093.       if(ap->Args[i].ArgReg >= REG_FP0)
  2094.       {
  2095.         struct ClibData *cd; 
  2096.  
  2097.         cd = GetClibFunc(ap->FuncName, ap, flags);
  2098.         *(data++) = 0xF22F;             /* FMOVE.? offs(A7),FPx */
  2099.  
  2100.         if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_DOUBLE))
  2101.         {
  2102.           *(data++) = 0x5400 + ((ap->Args[i++].ArgReg-REG_FP0)<<7);
  2103.           *(data++) = ofs<<2; /* one double needs two longs */
  2104.           ofs += 2;
  2105.         }
  2106.         else
  2107.         {
  2108.           if(!cd || !IsCPPType(&cd->Args[i], CPP_TYPE_FLOAT))
  2109.             DoError(ERR_LONG_DOUBLE, ap->Line);
  2110.           *(data++) = 0x4400 + ((ap->Args[i++].ArgReg-REG_FP0)<<7);
  2111.           *(data++) = (ofs++) << 2;
  2112.         }
  2113.       }
  2114.       else if(((k - i) >= 2) && (ap->Args[i].ArgReg < ap->Args[i+1].ArgReg)
  2115.       && ap->Args[i+1].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
  2116.       {
  2117.         *(data++) = 0x4CEF;             /* MOVEM.L offs(A7),xxx */
  2118.         *(data++) = 0;                  /* Store MOVEM.L data later */
  2119.         *(data++) = ofs << 2;           /* store start offset */
  2120.         do
  2121.         {
  2122.           j = ap->Args[i++].ArgReg;
  2123.  
  2124.           ++ofs;
  2125.           *(data-2) |= 1 << j;
  2126.         } while(i < k && j < ap->Args[i].ArgReg &&
  2127.         ap->Args[i].ArgReg < REG_FP0);
  2128.       }
  2129.       else
  2130.       {
  2131.         *data = 0x202F;                 /* MOVE.L offs(A7),xxx */
  2132.  
  2133.         if((j = ap->Args[i++].ArgReg) > 7)
  2134.         {
  2135.           *data |= (1<<6); j -= 8;      /* set MOVEA bit */
  2136.         }
  2137.         *(data++) |= j << 9;            /* set destination register */
  2138.         *(data++) = (ofs++) << 2;
  2139.       }
  2140.     }
  2141.  
  2142.     if(i < ap->NumArgs)
  2143.     {
  2144.       if((j = ap->Args[i].ArgReg) > 7)
  2145.       {
  2146.         *(data++) = 0x41EF | ((j-8) << 9);         /* LEA xxx(A7),Ax */
  2147.         *(data++) = ofs << 2;
  2148.       }
  2149.       else if(ofs == 2)
  2150.       {
  2151.         *(data++) = 0x200F | (j << 9);          /* MOVE.L A7,Dx */
  2152.         *(data++) = 0x5080 | j;                 /* ADDQ.L #8,Dx */
  2153.       }
  2154.       else
  2155.       {
  2156.         *(data++) = 0x486F;            /* PEA xxx(A7) */
  2157.         *(data++) = ofs << 2;
  2158.         *(data++) = 0x201F | j << 9;            /* MOVE.L offs(A7),Dx */
  2159.       }
  2160.     }
  2161.   }
  2162.  
  2163.   return data;
  2164. }
  2165. /* ------------------------------------------------------------------ */
  2166.  
  2167. void DoError(UBYTE errnum, ULONG line, ...)
  2168. {
  2169.   if(Flags & FLAG_DIDERROR)
  2170.     return;
  2171.  
  2172.   if(!Errors[errnum].Type)
  2173.     Flags |= FLAG_DIDERROR;
  2174.  
  2175.   Printf((line ? "%s %ld in line %ld%s: " : "%s %ld : "), (ULONG)
  2176.   (Errors[errnum].Type ? "Warning" : "Error"), errnum, line,
  2177.   errnum == ERR_UNKNOWN_VARIABLE_TYPE ? " of clib file" : "");
  2178.   VPrintf(Errors[errnum].Error, (((STRPTR) &line) + sizeof(ULONG)));
  2179.   PutStr("\n");
  2180.   if(line && Errors[errnum].Skip)
  2181.   {
  2182.     while(*in.pos)
  2183.       ++in.pos;
  2184.   }
  2185. }
  2186.  
  2187. ULONG CheckError(struct AmiPragma *ap, ULONG errflags)
  2188. {
  2189.   errflags &= ap->Flags;
  2190.  
  2191.   if(errflags & AMIPRAGFLAG_ARGCOUNT)
  2192.   {
  2193.     if(!(ap->Flags & AMIPRAGFLAG_DIDARGWARN))
  2194.     {
  2195.       DoError(ERR_ARGUMENTNUMBER_DIFFERS_FROM_REGISTERNUMBER, ap->Line);
  2196.       ap->Flags |= AMIPRAGFLAG_DIDARGWARN;
  2197.     }
  2198.     return 1;
  2199.   }
  2200.   else if(errflags & AMIPRAGFLAG_FLOATARG)
  2201.   {
  2202.     if(!(ap->Flags & AMIPRAGFLAG_DIDFLOATWARN))
  2203.     {
  2204.       DoError(ERR_FLOATARG_NOT_ALLOWED, ap->Line);
  2205.       ap->Flags |= AMIPRAGFLAG_DIDFLOATWARN;
  2206.     }
  2207.     return 1;
  2208.   }
  2209.   else if(errflags & AMIPRAGFLAG_A6USE)
  2210.   {
  2211.     DoError(ERR_A6_NOT_ALLOWED, ap->Line);
  2212.     return 1;
  2213.   }
  2214.   else if(errflags & AMIPRAGFLAG_A5USE)
  2215.   {
  2216.     DoError(ERR_A5_NOT_ALLOWED, ap->Line);
  2217.     return 1;
  2218.   }
  2219.   else if(errflags & AMIPRAGFLAG_PPC)
  2220.   {
  2221.     if(!(ap->Flags & AMIPRAGFLAG_DIDPPCWARN))
  2222.     {
  2223.       DoError(ERR_PPC_FUNCTION_NOT_SUPPORTED, ap->Line);
  2224.       ap->Flags |= AMIPRAGFLAG_DIDPPCWARN;
  2225.     }
  2226.     return 1;
  2227.   }
  2228.  
  2229.   return 0;
  2230. }
  2231.  
  2232. ULONG Out(ULONG size)
  2233. {
  2234.   ULONG i = out.pos-out.buf;
  2235.  
  2236.   if(i && out.size - i <= size)
  2237.   {
  2238.     if(Write(out.file, out.buf, i) != i)
  2239.     {
  2240.       Output_Error = 0;
  2241.       return 0;
  2242.     }
  2243.     out.pos = out.buf;
  2244.   }
  2245.   return out.size;
  2246. }
  2247.  
  2248. ASM(static void) SAVEDS putfunc(REG(d0, UBYTE data), REG(a3, LONG *a))
  2249. {
  2250. #ifdef __MAXON__
  2251.   GetBaseReg();
  2252. #endif
  2253.  
  2254.   if(data)
  2255.   {
  2256.     if(!*a)
  2257.       *a = Out(1);
  2258.     if((*a)-- > 0)
  2259.       *(out.pos++) = data;
  2260.   }
  2261. }
  2262.  
  2263. ULONG DoOutput(STRPTR format, ...)
  2264. {
  2265.   LONG a = out.buf+out.size-out.pos;
  2266.  
  2267.   if(!Output_Error)
  2268.     return 0;
  2269.  
  2270.   RawDoFmt(format, (APTR) ((ULONG)&format+sizeof(STRPTR)),
  2271.   (void(*)()) putfunc, &a);
  2272.  
  2273.   if(a < 0)
  2274.     return 0;
  2275.   return 1;
  2276. }
  2277.  
  2278. ULONG DoOutputDirect(APTR data, ULONG size)
  2279. {
  2280.   if(!Output_Error || !Out(size))
  2281.     return 0;
  2282.   CopyMem(data, out.pos, size);
  2283.   out.pos += size;
  2284.   return 1;
  2285. }
  2286.  
  2287. /* ------------------------------------------------------------------ */
  2288.  
  2289. struct ShortList *NewItem(struct ShortListRoot *list)
  2290. {
  2291.   struct ShortList *item;
  2292.   if(!list || !list->Size)
  2293.     return 0;
  2294.   if(!(item = (struct ShortList *) AllocListMem(list->Size)))
  2295.     return 0;
  2296.   return item;
  2297. }
  2298.  
  2299. struct ShortList *RemoveItem(struct ShortListRoot *list,
  2300. struct ShortList *item)
  2301. {
  2302.   struct ShortList *n = list->First;
  2303.  
  2304.   if(n == item)
  2305.     list->First = item->Next;
  2306.   else
  2307.   {
  2308.     while(n && n->Next != item)
  2309.       n = n->Next;
  2310.     if(!n)
  2311.       return 0;
  2312.     if(!(n->Next = item->Next))
  2313.       list->Last = n;
  2314.   }
  2315.   item->Next = 0;
  2316.   return item;
  2317. }
  2318.  
  2319. void AddItem(struct ShortListRoot *list, struct ShortList *item)
  2320. {
  2321.   if(!list->First)
  2322.     list->First = list->Last = item;
  2323.   else
  2324.   {
  2325.     list->Last->Next = item;
  2326.     list->Last = item;
  2327.   }
  2328. }
  2329.  
  2330. /* ------------------------------------------------------------------ */
  2331.  
  2332. ULONG FuncAMICALL(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2333. {
  2334.   ULONG i;
  2335.  
  2336.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  2337.     return 1;
  2338.  
  2339.   Flags |= FLAG_DONE; /* We did something */
  2340.  
  2341.   DoOutput("#pragma %s(%s,0x%03lx,%s("/*))*/, flags & FUNCFLAG_TAG ?
  2342.   "tagcall" : "amicall", BaseName, ap->Bias, name);
  2343.  
  2344.   for(i = 0; i < ap->NumArgs; ++i)
  2345.   {
  2346.     DoOutput(RegNames[ap->Args[i].ArgReg]);
  2347.     if(i+1 < ap->NumArgs)
  2348.       DoOutput(",");
  2349.   }
  2350.  
  2351.   return DoOutput(/*((*/"))\n");
  2352. }
  2353.  
  2354. ULONG FuncLIBCALL(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2355. {
  2356.   LONG i;
  2357.  
  2358.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  2359.     return 1;
  2360.  
  2361.   Flags |= FLAG_DONE; /* We did something */
  2362.  
  2363.   if(ap->Flags & AMIPRAGFLAG_FLOATARG)
  2364.   {
  2365.     DoOutput("#pragma flibcall %s %-20s %03lx ", BaseName, name, ap->Bias);
  2366.     for(i = ap->NumArgs-1; i >= 0; --i)
  2367.       DoOutput("%02lx", ap->Args[i].ArgReg);
  2368.  
  2369.     return DoOutput("00%02lx\n", ap->NumArgs);
  2370.   }
  2371.  
  2372.   if((Flags & FLAG_SYSCALL) && !strcmp(BaseName,"SysBase") &&
  2373.   (flags & FUNCFLAG_NORMAL))
  2374.     DoOutput("#pragma  syscall %-20s %03lx ", name, ap->Bias);
  2375.   else
  2376.     DoOutput("#pragma  %s %s %-20s %03lx ", (flags & FUNCFLAG_TAG) ?
  2377.     "tagcall" : "libcall", BaseName, name, ap->Bias);
  2378.  
  2379.   for(i = ap->NumArgs-1; i >= 0; --i)
  2380.     DoOutput("%lx", ap->Args[i].ArgReg);
  2381.  
  2382.   return DoOutput("0%lx\n", ap->NumArgs);
  2383. }
  2384.  
  2385. ULONG FuncAsmText(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2386. {
  2387.   LONG i;
  2388.   ULONG registers;
  2389.   UWORD fregs;
  2390.   ULONG offset = 1;
  2391.   STRPTR c1, c2;
  2392.   struct ClibData *cd;
  2393.  
  2394.   if(CheckError(ap, AMIPRAGFLAG_PPC))
  2395.     return 1;
  2396.  
  2397.   Flags |= FLAG_DONE; /* We did something */
  2398.  
  2399.   c1 = Flags & FLAG_NEWSYNTAX ? "(" : ""; /*)*/
  2400.   c2 = Flags & FLAG_NEWSYNTAX ? "," : "("; /*)*/
  2401.  
  2402.   if(Flags & FLAG_ASMSECTION)
  2403.   {
  2404.     DoOutput("\n\tSECTION\t\"%s\",CODE\n\tXREF\t_%s\n", name, BaseName);
  2405.   }
  2406.  
  2407.   DoOutput("\n\tXDEF\t_%s\n_%s:\n",name, name);
  2408.   if(!(Flags & FLAG_PASCAL))
  2409.   {
  2410.     DoOutput("\tXDEF\t%s\n%s:\n",name, name);
  2411.     if(clibdata)
  2412.     {
  2413.       if(!ap->NumArgs)
  2414.         DoOutput("\tXDEF\t%s_\n%s_:\n",name, name);
  2415.       else if((cd = GetClibFunc(name, ap, flags)))
  2416.       {
  2417.         UBYTE txt[300];
  2418.         ULONG ret = 0;
  2419.  
  2420.         do
  2421.         {
  2422.           if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
  2423.             DoOutput("\tXDEF\t%s__%s\n%s__%s:\n", name, txt, name, txt);
  2424.         } while(ret == 0xFFFFFFFF);
  2425.       }
  2426.     }
  2427.   }
  2428.  
  2429.   if((registers = GetRegisterData(ap) >> 16))
  2430.   {
  2431.     if(Flags & FLAG_NOMOVEM)
  2432.     {
  2433.       for(i = 0; i <= 15; ++i)
  2434.       {
  2435.         if(registers & (1 << i))
  2436.         {
  2437.           ++offset;
  2438.           DoOutput("\tMOVE.L\t%s,-(A7)\n", RegNamesUpper[i]);
  2439.         }
  2440.       }
  2441.     }
  2442.     else
  2443.     {
  2444.       UWORD l = registers;
  2445.  
  2446.       DoOutput("\tMOVEM.L\t");
  2447.  
  2448.       for(i = 0; i <= 15; ++i)
  2449.       {
  2450.         if(l & (1 << i))
  2451.         {
  2452.           ++offset;
  2453.           l ^= 1 << i;
  2454.           DoOutput(RegNamesUpper[i]);
  2455.           if(l)
  2456.             DoOutput("/");
  2457.         }
  2458.       }
  2459.       DoOutput(",-(A7)\n");
  2460.     }
  2461.   }
  2462.   else
  2463.   {
  2464.     DoOutput("\tMOVE.L\tA6,-(A7)\n"); ++offset;
  2465.   }
  2466.  
  2467.   if((fregs = GetFRegisterData(ap) >> 8))
  2468.   {
  2469.     UBYTE l = fregs;
  2470.  
  2471.     DoOutput("\tFMOVEM.X\t");
  2472.  
  2473.     for(i = 0; i <= 7; ++i)
  2474.     {
  2475.       if(l & (1 << i))
  2476.       {
  2477.         offset += 3;
  2478.         l ^= 1 << i;
  2479.         DoOutput(RegNamesUpper[REG_FP0 + i]);
  2480.         if(l)
  2481.           DoOutput("/");
  2482.       }
  2483.     }
  2484.     DoOutput(",-(A7)\n");
  2485.   }
  2486.  
  2487.   if(Flags & FLAG_SMALLDATA)
  2488.   {
  2489.     DoOutput(/*(*/"\tMOVEA.L\t%s_%s%sA4),A6\n", c1, BaseName, c2);
  2490.   }
  2491.   else
  2492.     DoOutput("\tMOVEA.L\t_%s,A6\n", BaseName);
  2493.  
  2494.   if(!(Flags & FLAG_PASCAL))
  2495.   {
  2496.     ULONG k;
  2497.  
  2498.     k = ap->NumArgs - ((flags & FUNCFLAG_TAG) ? 1 : 0);
  2499.  
  2500.     for(i = 0; i < k;)
  2501.     {
  2502.       if(ap->Args[i].ArgReg >= REG_FP0)
  2503.       {
  2504.         ULONG t;
  2505.         struct ClibData *cd;
  2506.  
  2507.         cd = GetClibFunc(name, ap, flags);
  2508.         if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_DOUBLE))
  2509.           t = CPP_TYPE_DOUBLE;
  2510.         else if(cd && IsCPPType(&cd->Args[i], CPP_TYPE_FLOAT))
  2511.           t = CPP_TYPE_FLOAT;
  2512.         else
  2513.         {
  2514.           DoError(ERR_LONG_DOUBLE, ap->Line);
  2515.           t = CPP_TYPE_FLOAT;
  2516.         }
  2517.  
  2518.         DoOutput(/*(*/"\tFMOVE.%lc\t%s%02ld%sA7),%s\n", t == CPP_TYPE_DOUBLE ? 'D' : 'S', c1,
  2519.         offset<<2, c2, RegNamesUpper[ap->Args[i++].ArgReg]);
  2520.  
  2521.         if(t == CPP_TYPE_DOUBLE)
  2522.           ++offset;
  2523.         ++offset;
  2524.       }
  2525.       else if(((k - i) >= 2) && (ap->Args[i].ArgReg < ap->Args[i+1].ArgReg) &&
  2526.       ap->Args[i+1].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
  2527.       {
  2528.         DoOutput(/*(*/"\tMOVEM.L\t%s%02ld%sA7),%s", c1, (offset++)<<2, c2,
  2529.         RegNamesUpper[ap->Args[i++].ArgReg]);
  2530.  
  2531.         do
  2532.         {
  2533.           DoOutput("/%s", RegNamesUpper[ap->Args[i++].ArgReg]);
  2534.           ++offset;
  2535.         } while((i < k) && (ap->Args[i-1].ArgReg < ap->Args[i].ArgReg) &&
  2536.         ap->Args[i].ArgReg < REG_FP0);
  2537.         DoOutput("\n");
  2538.       }
  2539.       else
  2540.       {
  2541.         DoOutput(/*(*/"\tMOVE%s.L\t%s%02ld%sA7),%s\n",
  2542.         ap->Args[i].ArgReg >= REG_A0 ? "A" : "", c1, (offset++)<<2, c2,
  2543.         RegNamesUpper[ap->Args[i].ArgReg]);
  2544.         ++i;
  2545.       }
  2546.     }
  2547.  
  2548.     if(i < ap->NumArgs)
  2549.     {
  2550.       if(ap->Args[i].ArgReg > 7)
  2551.         DoOutput(/*(*/"\tLEA\t%s%02ld%sA7),%s\n", c1, offset<<2, c2,
  2552.         RegNamesUpper[ap->Args[i].ArgReg]);
  2553.       else if(offset <= 2)
  2554.         DoOutput("\tMOVE.L\tA7,%s\n\tADDQ.L\t#%02ld,%s\n",
  2555.         RegNamesUpper[ap->Args[i].ArgReg],offset<<2,
  2556.         RegNamesUpper[ap->Args[i].ArgReg]);
  2557.       else
  2558.         DoOutput(/*(*/"\tPEA\t%s%ld%sA7)\n\tMOVE.L\t(A7)+,%s\n",c1,
  2559.         offset<<2, c2,RegNamesUpper[ap->Args[i].ArgReg]);
  2560.     }
  2561.   }
  2562.   else
  2563.   {
  2564.     i = ap->NumArgs;
  2565.  
  2566.     while(i)
  2567.     {
  2568.       if(ap->Args[i-1].ArgReg >= REG_FP0)
  2569.       {
  2570.         ULONG t;
  2571.         struct ClibData *cd;
  2572.  
  2573.         cd = GetClibFunc(name, ap, flags);
  2574.  
  2575.         if(cd && IsCPPType(&cd->Args[i-1], CPP_TYPE_DOUBLE))
  2576.           t = CPP_TYPE_DOUBLE;
  2577.         else if(cd && IsCPPType(&cd->Args[i-1], CPP_TYPE_FLOAT))
  2578.           t = CPP_TYPE_FLOAT;
  2579.         else
  2580.         {
  2581.           DoError(ERR_LONG_DOUBLE, ap->Line);
  2582.           t = CPP_TYPE_FLOAT;
  2583.         }
  2584.  
  2585.         DoOutput(/*(*/"\tFMOVE.%lc\t%s%02ld%sA7),%s\n", t == CPP_TYPE_DOUBLE ? 'D' : 'S',
  2586.         c1, offset<<2, c2, RegNamesUpper[ap->Args[--i].ArgReg]);
  2587.         if(t == CPP_TYPE_DOUBLE)
  2588.           ++offset;
  2589.         ++offset;
  2590.       }
  2591.       else if((i >= 2) && (ap->Args[i-1].ArgReg < ap->Args[i-2].ArgReg) &&
  2592.       ap->Args[i-2].ArgReg < REG_FP0 && !(Flags & FLAG_NOMOVEM))
  2593.       {
  2594.         DoOutput(/*(*/"\tMOVEM.L\t%s%02ld%sA7),%s", c1, (offset++)<<2, c2,
  2595.         RegNamesUpper[ap->Args[--i].ArgReg]);
  2596.  
  2597.         do
  2598.         {
  2599.           DoOutput("/%s", RegNamesUpper[ap->Args[--i].ArgReg]);
  2600.           ++offset;
  2601.         } while(i && (ap->Args[i].ArgReg < ap->Args[i-1].ArgReg) &&
  2602.         ap->Args[i-1].ArgReg < REG_FP0);
  2603.         DoOutput("\n");
  2604.       }
  2605.       else
  2606.       {
  2607.         --i;
  2608.         DoOutput(/*(*/"\tMOVE%s.L\t%s%02ld%sA7),%s\n",
  2609.         ap->Args[i].ArgReg >= REG_A0 ? "A" : "", c1, (offset++)<<2, c2,
  2610.         RegNamesUpper[ap->Args[i].ArgReg]);
  2611.       }
  2612.     }
  2613.   }
  2614.  
  2615.   DoOutput(/*(*/"\tJSR\t%s-%03ld%sA6)\n", c1, ap->Bias, c2);
  2616.  
  2617.   if(fregs)
  2618.   {
  2619.     DoOutput("\tFMOVEM.X\t(A7)+,");
  2620.  
  2621.     for(i = 0; i <= 7; ++i)
  2622.     {
  2623.       if(fregs & (1 << i))
  2624.       {
  2625.         fregs ^= 1 << i;
  2626.         DoOutput(RegNamesUpper[REG_FP0 + i]);
  2627.         if(fregs)
  2628.           DoOutput("/");
  2629.       }
  2630.     }
  2631.     DoOutput("\n");
  2632.   }
  2633.  
  2634.   if(registers)
  2635.   {
  2636.     if(Flags & FLAG_NOMOVEM)
  2637.     {
  2638.       for(i = 15; i >= 0; --i)
  2639.       {
  2640.         if(registers & (1 << i))
  2641.           DoOutput("\tMOVE%s.L\t(A7)+,%s\n", i >= REG_A0 ? "A" : "", RegNamesUpper[i]);
  2642.       }
  2643.     }
  2644.     else
  2645.     {
  2646.       DoOutput("\tMOVEM.L\t(A7)+,");
  2647.  
  2648.       for(i = 0; i <= 15; ++i)
  2649.       {
  2650.         if(registers & (1 << i))
  2651.         {
  2652.           registers ^= 1 << i;
  2653.           DoOutput(RegNamesUpper[i]);
  2654.           if(registers)
  2655.             DoOutput("/");
  2656.         }
  2657.       }
  2658.       DoOutput("\n");
  2659.     }
  2660.   }
  2661.   else
  2662.     DoOutput("\tMOVEA.L\t(A7)+,A6\n");
  2663.  
  2664.   return DoOutput("\tRTS\n");
  2665. }
  2666.  
  2667. ULONG FuncAsmCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2668. {
  2669.   ULONG registers, a[5], offset = 1, pos = 4, baseref;
  2670.   LONG i = strlen(ShortBaseNameUpper);
  2671.   UWORD *data;
  2672.   UWORD fregs;
  2673.  
  2674.   data = (UWORD *) tempbuf;
  2675.  
  2676.   if(CheckError(ap, AMIPRAGFLAG_PPC))
  2677.     return 1;
  2678.  
  2679.   Flags |= FLAG_DONE; /* We did something */
  2680.  
  2681.   registers = GetRegisterData(ap);
  2682.  
  2683.   fregs = GetFRegisterData(ap);
  2684.  
  2685.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  2686.   a[3] = (i + 6 + 3)>>2;
  2687.  
  2688.   DoOutputDirect(a, 16);
  2689.   DoOutputDirect(ShortBaseNameUpper, i);
  2690.   DoOutputDirect("_STUBS\0\0\0", (a[3]<<2)-i);
  2691.  
  2692.   data[0] = 0;
  2693.   data[1] = HUNK_CODE;
  2694.   data[2] = 0;
  2695.   /* data[3] is size */
  2696.  
  2697.   if(!registers)
  2698.   {
  2699.     data[pos++] = 0x2F0E;               /* MOVE.L A6,-(A7) */
  2700.     ++offset;                           /* one long more on stack */
  2701.   }
  2702.   else
  2703.   {
  2704.     if(Flags & FLAG_NOMOVEM)
  2705.     {
  2706.       for(i = 0; i <= 15; ++i)
  2707.       {
  2708.         if(registers & (1<< (16+i)))
  2709.         {
  2710.           data[pos++] = 0x2F00 + i;     /* MOVE.L xxx,-(A7) */
  2711.           ++offset;
  2712.         }
  2713.       }
  2714.     }
  2715.     else
  2716.     {
  2717.       ULONG l;
  2718.       data[pos++] = 0x48E7;             /* MOVEM.L xxx,-(A7) */
  2719.       data[pos++] = registers;          /* store MOVEM.L registers */
  2720.       for(l = (UWORD) registers; l; l >>= 1)
  2721.       {
  2722.         if(l & 1)
  2723.           ++offset;                     /* get offset addition */
  2724.       }
  2725.     }
  2726.   }
  2727.  
  2728.   if(fregs)
  2729.   {
  2730.     ULONG l;
  2731.     data[pos++] = 0xF227;               /* FMOVEM.X xxx,-(A7) */
  2732.     data[pos++] = 0xE000 + ((fregs>>8)&0xFF);
  2733.     for(l = (UBYTE) fregs; l; l >>= 1)
  2734.     {
  2735.       if(l & 1)
  2736.         offset+=3;                      /* get offset addition */
  2737.     }
  2738.   }
  2739.  
  2740.   baseref = pos+1-4;                    /* one word later (MOVE) - 2 header longs */
  2741.   if(Flags & FLAG_SMALLDATA)
  2742.   {
  2743.     data[pos++] = 0x2C6C;               /* MOVEA.L base(A4),A6 */
  2744.     data[pos++] = 0;                    /* place for base reference */
  2745.   }
  2746.   else
  2747.   {
  2748.     data[pos++] = 0x2C79;               /* MOVEA.L base,A6 */
  2749.     data[pos++] = 0;                    /* place for base reference */
  2750.     data[pos++] = 0;
  2751.   }
  2752.  
  2753.   pos = AsmStackCopy(data+pos, ap, flags, offset) - data;
  2754.  
  2755.   /* here comes the base reference */
  2756.   data[pos++] = 0x4EAE;                 /* JSR xxx(A6) */
  2757.   data[pos++] = -ap->Bias;              /* JSR offset */
  2758.  
  2759.   if(fregs)
  2760.   {
  2761.     data[pos++] = 0xF21F;               /* FMOVEM.X (A7)+,xxx */
  2762.     data[pos++] = 0xD000 + (fregs&0xFF);
  2763.   }
  2764.  
  2765.   if(registers)
  2766.   {
  2767.     if(Flags & FLAG_NOMOVEM)
  2768.     {
  2769.       for(i = 15; i >= 0; --i)
  2770.       {
  2771.         if(registers & (1<<(16+i)))     /* MOVE.L (A7)+,xxx */
  2772.           data[pos++] = 0x201F + ((i&7)<<9) + ((i>>3)<<6);
  2773.       }
  2774.     }
  2775.     else
  2776.     {
  2777.       data[pos++] = 0x4CDF;             /* MOVEM.L (A7)+,xxx */
  2778.       data[pos++] = (registers >> 16);  /* store MOVEM.L registers */
  2779.     }
  2780.   }
  2781.   else
  2782.     data[pos++] = 0x2C5F;               /* MOVE.L (A7)+,A6 */
  2783.   data[pos++] = 0x4E75;                 /* RTS */
  2784.  
  2785.   if(pos & 1)
  2786.     data[pos++] = 0;                    /* round to long */
  2787.  
  2788.   data[3] = (pos-4)>>1;                 /* store hunk len */
  2789.   DoOutputDirect(data, pos<<1);
  2790.  
  2791.   a[0] = HUNK_EXT;
  2792.   a[1] = ((Flags & FLAG_SMALLDATA ? EXT_REF16 : EXT_REF32) << 24) +
  2793.          ((strlen(BaseName) + 1 + 3)>>2);
  2794.   a[2] = ('_' << 24);
  2795.  
  2796.   DoOutputDirect(a, 9);
  2797.   DoOutputDirect(BaseName, (((UWORD) a[1])<<2)-1);
  2798.  
  2799.   a[0] = 1; a[1] = baseref << 1;
  2800.   DoOutputDirect(a, 8);
  2801.  
  2802.   /* here come the XDEF name references */
  2803.   OutputXDEF("_%s", name);              /* C name */
  2804.  
  2805.   if(!(Flags & FLAG_PASCAL))
  2806.   {
  2807.     struct ClibData *cd;
  2808.     OutputXDEF("%s", name);             /* ASM name */
  2809.  
  2810.     if(clibdata)
  2811.     {
  2812.       if(!ap->NumArgs)
  2813.         OutputXDEF("%s_", name);        /* C++ name no parameters */
  2814.       else if((cd = GetClibFunc(name, ap, flags)))
  2815.       {
  2816.         ULONG ret = 0;
  2817.  
  2818.         do                              /* C++ name with parameters */
  2819.         {
  2820.           if((ret = CopyCPPType((STRPTR) data, ret, cd, ap->Args)))
  2821.             OutputXDEF("%s__%s", name, (STRPTR) data);
  2822.         } while(ret == 0xFFFFFFFF);
  2823.       }
  2824.     }
  2825.   }
  2826.  
  2827.   a[0] = 0;
  2828.   DoOutputDirect(a, 4);
  2829.   if(!(Flags & FLAG_NOSYMBOL))
  2830.   {
  2831.     a[0] = HUNK_SYMBOL;
  2832.     DoOutputDirect(a, 4);
  2833.     OutputSYMBOL("_%s", name);              /* C name */
  2834.  
  2835.     if(!(Flags & FLAG_PASCAL))
  2836.     {
  2837.       struct ClibData *cd;
  2838.       OutputSYMBOL("%s", name);             /* ASM name */
  2839.  
  2840.       if(clibdata)
  2841.       {
  2842.         if(!ap->NumArgs)
  2843.           OutputSYMBOL("%s_", name);        /* C++ name no parameters */
  2844.         else if((cd = GetClibFunc(name, ap, flags)))
  2845.         {
  2846.           ULONG ret = 0;
  2847.  
  2848.           do                              /* C++ name with parameters */
  2849.           {
  2850.             if((ret = CopyCPPType((STRPTR) data, ret, cd, ap->Args)))
  2851.               OutputSYMBOL("%s__%s", name, (STRPTR) data);
  2852.           } while(ret == 0xFFFFFFFF);
  2853.         }
  2854.       }
  2855.     }
  2856.  
  2857.     a[0] = 0;
  2858.     DoOutputDirect(a, 4);
  2859.   }
  2860.  
  2861.   a[0] = HUNK_END;
  2862.  
  2863.   return DoOutputDirect(a, 4);
  2864. }
  2865.  
  2866. /* Directly called by FuncInline also! */
  2867. ULONG FuncCSTUBS(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2868. {
  2869.   struct ClibData *f, *t;
  2870.   STRPTR ret = "return ";
  2871.   ULONG i;
  2872.  
  2873.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  2874.     return 1;
  2875.  
  2876.   Flags |= FLAG_DONE; /* We did something */
  2877.  
  2878.   if(!(f = GetClibFunc(ap->FuncName, ap, 0)))
  2879.     return 1;
  2880.   t = GetClibFunc(name, ap, flags);
  2881.  
  2882.   if(IsCPPType(&f->ReturnType, CPP_TYPE_VOID))
  2883.     ret = 0;
  2884.  
  2885.   if(!OutClibType(&f->ReturnType, name) || !DoOutput("("/*)*/))
  2886.     return 0;
  2887.   for(i = 0; i < ap->NumArgs-1; i++)
  2888.   {
  2889.     if(!OutClibType(&f->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
  2890.       return 0;
  2891.   }
  2892.   if(t && t->Args[i].Type != CPP_TYPE_VARARGS)
  2893.   {
  2894.     if(!OutClibType(&t->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
  2895.       return 0;
  2896.   }
  2897.   else if(ap->NumArgs == 1 && !DoOutput("ULONG tag, "))
  2898.     return 0;
  2899.  
  2900.   if(!DoOutput(/*(*/"...)\n{\n  %s%s("/*)*/, ret, ap->FuncName))
  2901.     return 0;
  2902.   for(i = 0; i < ap->NumArgs-1; i++)
  2903.   {
  2904.     if(!DoOutput("%s, ", ap->Args[i].ArgName))
  2905.       return 0;
  2906.   }
  2907.   if(!DoOutput("("/*)*/) || !OutClibType(&f->Args[ap->NumArgs-1],0))
  2908.     return 0;
  2909.  
  2910.   if(t && t->Args[i].Type != CPP_TYPE_VARARGS)
  2911.   {
  2912.     if(!DoOutput(/*((*/") &%s);\n}\n\n", ap->Args[ap->NumArgs-1].ArgName))
  2913.       return 0;
  2914.   }
  2915.   else if(ap->NumArgs == 1)
  2916.   {
  2917.     if(!DoOutput(/*((*/") &tag);\n}\n\n"))
  2918.       return 0;
  2919.   }
  2920.   else if (!DoOutput(/*(*/") ((ULONG) &%s + sizeof("/*))*/,
  2921.   ap->Args[ap->NumArgs-2].ArgName) || !OutClibType(&f->Args[ap->NumArgs-2],0)
  2922.   || !DoOutput(/*(((*/")));\n}\n\n"))
  2923.     return 0;
  2924.   return 1;
  2925. }
  2926.  
  2927. ULONG FuncLVOXDEF(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2928. {
  2929.   Flags |= FLAG_DONE; /* We did something */
  2930.   return DoOutput("\t\tXDEF\t_LVO%s\n", name);
  2931. }
  2932.  
  2933. ULONG FuncLVO(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2934. {
  2935.   Flags |= FLAG_DONE; /* We did something */
  2936.   return DoOutput("\n_LVO%-24s\tEQU\t-%ld", name, ap->Bias);
  2937. }
  2938.  
  2939. ULONG FuncLVOLib(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2940. {
  2941.   ULONG a[1], j;
  2942.  
  2943.   Flags |= FLAG_DONE; /* We did something */
  2944.   a[0] = (EXT_ABS << 24) + (((j=strlen(name)) + 4 + 3)>>2);
  2945.  
  2946.   DoOutputDirect(a, 4);
  2947.   DoOutputDirect("_LVO", 4);
  2948.   DoOutputDirect(name, j);
  2949.   DoOutputDirect("\0\0\0", ((j+3)&(~3))-j);
  2950.   a[0] = -ap->Bias;
  2951.   return DoOutputDirect(a, 4);
  2952. }
  2953.  
  2954. ULONG FuncLocCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
  2955. {
  2956.   ULONG a[5];
  2957.   STRPTR str2 = Flags & FLAG_LOCALREG ? "rE" : "";
  2958.   LONG i = strlen(ShortBaseNameUpper);
  2959.   ULONG j;
  2960.   struct ClibData *cd = 0;
  2961.  
  2962.   if(CheckError(ap, AMIPRAGFLAG_PPC))
  2963.     return 1;
  2964.  
  2965.   Flags |= FLAG_DONE; /* We did something */
  2966.  
  2967.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  2968.   a[3] = (i + 4 + 3)>>2;
  2969.  
  2970.   DoOutputDirect(a, 16);
  2971.   DoOutputDirect(ShortBaseNameUpper, i);
  2972.   DoOutputDirect("_LOC\0\0\0", (a[3]<<2)-i);
  2973.  
  2974.   if(Flags & FLAG_LOCALREG)
  2975.   {
  2976.     if((flags & FUNCFLAG_TAG))
  2977.     {
  2978.       j = ap->Args[ap->NumArgs-1].ArgReg;
  2979.       a[0] = HUNK_CODE; a[1] = 4;
  2980.       a[2] = 0x2F000000 + (j << 16);    /* MOVE <ea>,-(A7) */
  2981.  
  2982.       DoOutputDirect(a, 10);
  2983.  
  2984.       a[1] = 0x4EAE0000 + (UWORD) (- ap->Bias); /* JSR instruction */
  2985.       a[2] = 0x201F4E75;                /* MOVE (A7)+,<ea> */
  2986.       a[3] = 0;
  2987.       if(j > 7)
  2988.       {                                 /* LEA x(A7),Ax */
  2989.         j -= 8;
  2990.         a[0] = 0x41EF0008 | (j << 25);
  2991.         a[2] += 0x400000;               /* set A flag */
  2992.       }
  2993.       else
  2994.       {                                 /* MOVE.L A7,Dx  -- ADDQ.L #8,Dx */
  2995.         a[0] = 0x200F5080 | j | (j << 25);
  2996.       }
  2997.       a[2] += j << 25;
  2998.  
  2999.       DoOutputDirect(a, 14);
  3000.     }
  3001.     else
  3002.     {
  3003.       a[0] = HUNK_CODE; a[1] = 1;
  3004.       a[2] = 0x4EEE0000 + (UWORD) (- ap->Bias); /* JMP instruction */
  3005.       DoOutputDirect(a, 12);
  3006.     }
  3007.   }
  3008.   else
  3009.   {
  3010.     ULONG registers, offset = 1, pos = 4;
  3011.     UWORD *data;
  3012.  
  3013.     data = (UWORD *) tempbuf;
  3014.  
  3015.     registers = GetRegisterData(ap);
  3016.  
  3017.     data[0] = 0;
  3018.     data[1] = HUNK_CODE;
  3019.     data[2] = 0;
  3020.     /* data[3] is size */
  3021.  
  3022.     if(!registers) /* happens only when !(ap->Flags & AMIPRAG_A6USE) */
  3023.     {
  3024.       data[pos++] = 0x2F0E;             /* MOVE.L A6,-(A7) */
  3025.       ++offset;                         /* one long more on stack */
  3026.     }
  3027.     else
  3028.     {
  3029.       if(Flags & FLAG_NOMOVEM)
  3030.       {
  3031.         for(i = 0; i <= 15; ++i)
  3032.         {
  3033.           if(registers & (1<< (16+i)))
  3034.           {
  3035.             data[pos++] = 0x2F00 + i;   /* MOVE.L xxx,-(A7) */
  3036.             ++offset;
  3037.           }
  3038.         }
  3039.       }
  3040.       else
  3041.       {
  3042.         ULONG l;
  3043.         data[pos++] = 0x48E7;           /* MOVEM.L xxx,-(A7) */
  3044.         data[pos++] = registers;        /* store MOVEM.L registers */
  3045.         for(l = (UWORD) registers; l; l >>= 1)
  3046.         {
  3047.           if(l & 1)
  3048.             ++offset;                   /* get offset addition */
  3049.         }
  3050.       }
  3051.     }
  3052.  
  3053.     if(!(ap->Flags & AMIPRAGFLAG_A6USE)) /* store library base in A6 */
  3054.     {
  3055.       data[pos++] = 0x2C6F;             /* MOVE.L ofs(A7),A6 */
  3056.       data[pos++] = (offset++) << 2;
  3057.     }
  3058.  
  3059.     pos = AsmStackCopy(data+pos, ap, flags, offset) - data;
  3060.  
  3061.     /* here comes the base reference */
  3062.     data[pos++] = 0x4EAE;               /* JSR xxx(A6) */
  3063.     data[pos++] = -ap->Bias;            /* JSR offset */
  3064.     if(registers)
  3065.     {
  3066.       if(Flags & FLAG_NOMOVEM)
  3067.       {
  3068.         for(i = 15; i >= 0; --i)
  3069.         {
  3070.           if(registers & (1<<(16+i)))   /* MOVE.L (A7)+,xxx */
  3071.             data[pos++] = 0x201F + ((i&7)<<9) + ((i>>3)<<6);
  3072.         }
  3073.       }
  3074.       else
  3075.       {
  3076.         data[pos++] = 0x4CDF;           /* MOVEM.L (A7)+,xxx */
  3077.         data[pos++] = (registers >> 16); /* store MOVEM.L registers */
  3078.       }
  3079.     }
  3080.     else
  3081.       data[pos++] = 0x2C5F;             /* MOVE.L (A7)+,A6 */
  3082.  
  3083.     data[pos++] = 0x4E75;               /* RTS */
  3084.  
  3085.     if(pos & 1)
  3086.       data[pos++] = 0;                  /* round to long */
  3087.  
  3088.     data[3] = (pos-4)>>1;               /* store hunk len */
  3089.     DoOutputDirect(data, pos<<1);
  3090.   }
  3091.  
  3092.   a[0] = HUNK_EXT;
  3093.   DoOutputDirect(a,4);
  3094.  
  3095.   /* here come the XDEF name references */
  3096.  
  3097.   OutputXDEF("%s", name);               /* ASM names */
  3098.   OutputXDEF("LOC_%s", name);
  3099.  
  3100.   OutputXDEF("_%s", name);              /* C names */
  3101.   OutputXDEF("_LOC_%s", name);
  3102.  
  3103.   if(!ap->NumArgs && clibdata)
  3104.   {
  3105.     OutputXDEF("%s__%sP07Library", name, str2); /* C++ names no parameters */
  3106.     OutputXDEF("LOC_%s__%sP07Library", name, str2);
  3107.   }
  3108.   else if((cd = GetClibFunc(name, ap, flags)))
  3109.   {
  3110.     STRPTR txt;
  3111.     ULONG ret = 0;
  3112.     
  3113.     txt = (STRPTR) tempbuf;
  3114.  
  3115.     do
  3116.     {
  3117.       if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
  3118.       {                                 /* C++ names with parameters */
  3119.         if(!(ap->Flags & AMIPRAGFLAG_A6USE))
  3120.         {
  3121.           OutputXDEF("%s__%sP07Library%s", name, str2, txt);
  3122.           OutputXDEF("LOC_%s__%sP07Library%s", name, str2, txt);
  3123.         }
  3124.         else
  3125.         {
  3126.           OutputXDEF("%s__%s", name, txt);
  3127.           OutputXDEF("LOC_%s__%s", name, txt);
  3128.         }
  3129.       }
  3130.     } while(ret == 0xFFFFFFFF);
  3131.   }
  3132.  
  3133.   a[0] = 0;
  3134.   DoOutputDirect(a, 4);
  3135.   if(!(Flags & FLAG_NOSYMBOL))
  3136.   {
  3137.     a[0] = HUNK_SYMBOL;
  3138.     DoOutputDirect(a, 4);
  3139.     OutputSYMBOL("%s", name);               /* ASM names */
  3140.     OutputSYMBOL("LOC_%s", name);
  3141.  
  3142.     OutputSYMBOL("_%s", name);              /* C names */
  3143.     OutputSYMBOL("_LOC_%s", name);
  3144.  
  3145.     if(!ap->NumArgs && clibdata)
  3146.     {
  3147.       OutputSYMBOL("%s__%sP07Library", name, str2); /* C++ names no parameters */
  3148.       OutputSYMBOL("LOC_%s__%sP07Library", name, str2);
  3149.     }
  3150.     else if(cd)
  3151.     {
  3152.       STRPTR txt;
  3153.       ULONG ret = 0;
  3154.     
  3155.       txt = (STRPTR) tempbuf;
  3156.  
  3157.       do
  3158.       {
  3159.         if((ret = CopyCPPType(txt, ret, cd, ap->Args)))
  3160.         {                                 /* C++ names with parameters */
  3161.           if(!(ap->Flags & AMIPRAGFLAG_A6USE))
  3162.           {
  3163.             OutputSYMBOL("%s__%sP07Library%s", name, str2, txt);
  3164.             OutputSYMBOL("LOC_%s__%sP07Library%s", name, str2, txt);
  3165.           }
  3166.           else
  3167.           {
  3168.             OutputSYMBOL("%s__%s", name, txt);
  3169.             OutputSYMBOL("LOC_%s__%s", name, txt);
  3170.           }
  3171.         }
  3172.       } while(ret == 0xFFFFFFFF);
  3173.     }
  3174.  
  3175.     a[0] = 0;
  3176.     DoOutputDirect(a, 4);
  3177.   }
  3178.   a[0] = HUNK_END;
  3179.  
  3180.   return DoOutputDirect(a, 4);
  3181. }
  3182.  
  3183. ULONG FuncLocText(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3184. {
  3185.   struct ClibData *cd;
  3186.   LONG i;
  3187.  
  3188.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  3189.     return 1;
  3190.  
  3191.   Flags |= FLAG_DONE; /* We did something */
  3192.  
  3193.   if(!(cd = GetClibFunc(name, ap, flags)))
  3194.     return 1;
  3195.  
  3196.   OutClibType(&cd->ReturnType, 0);
  3197.   DoOutput(" LOC_%s("/*)*/, name);
  3198.   if(!(ap->Flags & AMIPRAGFLAG_A6USE))
  3199.   {
  3200.     if(Flags & FLAG_LOCALREG)
  3201.       DoOutput("register __a6 ");
  3202.     DoOutput("struct Library * libbase");
  3203.     if(ap->NumArgs)
  3204.       DoOutput(", ");
  3205.   }
  3206.  
  3207.   if(ap->NumArgs)
  3208.   {
  3209.     for(i = 0; i < ap->NumArgs-1; i++)
  3210.     {
  3211.       if(((Flags & FLAG_LOCALREG &&
  3212.       !DoOutput("register __%s ", RegNames[ap->Args[i].ArgReg]))) ||
  3213.       !OutClibType(&cd->Args[i], ap->Args[i].ArgName) || !DoOutput(", "))
  3214.         return 0;
  3215.     }
  3216.  
  3217.     if(flags & FUNCFLAG_NORMAL)
  3218.     {
  3219.       if(((Flags & FLAG_LOCALREG &&
  3220.       !DoOutput("register __%s ", RegNames[ap->Args[i].ArgReg]))) ||
  3221.       !OutClibType(&cd->Args[i], ap->Args[i].ArgName) ||
  3222.       !DoOutput(/*(*/");\n"))
  3223.         return 0;
  3224.       if(BaseName)
  3225.       {
  3226.         DoOutput("#define %s("/*)*/, name);
  3227.         for(i = 0; i < ap->NumArgs-1; ++i)
  3228.           DoOutput("%lc, ", (i+'a'));
  3229.         DoOutput(/*(*/"%lc) LOC_%s((struct Library *) %s, "/*)*/,(i+'a'),
  3230.         name, BaseName);
  3231.         for(i = 0; i < ap->NumArgs-1; ++i)
  3232.           DoOutput("%lc, ",(i+'a'));
  3233.         return DoOutput(/*(*/"%lc)\n\n",(i+'a'));
  3234.       }
  3235.     }
  3236.     else
  3237.       return DoOutput(/*(*/"...);\n");
  3238.   }
  3239.   else if(BaseName)
  3240.     return DoOutput(/*(*/");\n#define %s(a) LOC_%s((struct Library *) a)\n\n",
  3241.     name, name);
  3242.   else
  3243.     return DoOutput(/*(*/");\n");
  3244.   return 1;
  3245. }
  3246.  
  3247. ULONG FuncInline(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3248. {
  3249.   ULONG noret = 0, a45 = 0, i, j;
  3250.   LONG fp = -1;
  3251.   struct ClibData *cd;
  3252.  
  3253.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  3254.     return 1;
  3255.  
  3256.   Flags |= FLAG_DONE; /* We did something */
  3257.  
  3258.   if(flags & FUNCFLAG_ALIAS)
  3259.   {
  3260.     if(flags & FUNCFLAG_TAG)
  3261.       return DoOutput("#ifndef NO_%sINLINE_STDARG\n#define %s %s\n#endif\n\n",
  3262.       Flags & FLAG_POWERUP ? "PPC" : "", name, ap->TagName);
  3263.  
  3264.     DoOutput("#define %s("/*)*/, name);
  3265.     for(i = 0; i < ap->NumArgs-1; ++i)
  3266.       DoOutput("%s, ", ap->Args[i].ArgName);
  3267.     DoOutput(/*(*/"%s) %s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
  3268.     for(i = 0; i < ap->NumArgs-1; ++i)
  3269.       DoOutput("(%s), ", ap->Args[i].ArgName);
  3270.     return DoOutput(/*(*/"(%s))\n\n", ap->Args[i].ArgName);
  3271.   }
  3272.  
  3273.   if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  3274.     return 1;
  3275.  
  3276.   if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3277.     noret = 1; /* this is a void function */
  3278.  
  3279.   if(ap->Flags & AMIPRAGFLAG_A5USE)
  3280.     a45 = REG_A5;
  3281.   if(ap->Flags & AMIPRAGFLAG_A4USE)
  3282.   {
  3283.     if(a45)
  3284.     {
  3285.       DoError(ERR_INLINE_A4_AND_A5, ap->Line);
  3286.       return 1; /* skip this entry */
  3287.     }
  3288.     a45 = REG_A4;
  3289.   }
  3290.   if(a45 && (ap->Flags & AMIPRAGFLAG_D7USE))
  3291.   {
  3292.     DoError(ERR_INLINE_D7_AND_A45, ap->Line);
  3293.     return 1; /* skip this entry */
  3294.   }
  3295.  
  3296.   if((flags & FUNCFLAG_TAG))
  3297.   {
  3298.     if(!(Flags & FLAG_INLINESTUB)) /* no stubs */
  3299.     {
  3300.       DoOutput("#ifndef NO_%sINLINE_STDARG\n#define %s("/*)*/, 
  3301.       Flags & FLAG_POWERUP ? "PPC" : "", name);
  3302.       for(i = 0; i < ap->NumArgs-1; ++i)
  3303.       {
  3304.         DoOutput("%s, ", ap->Args[i].ArgName);
  3305.       }
  3306.       DoOutput(/*(*/"tags...) \\\n\t({ULONG _tags[] = {tags}; %s("/*}))*/,
  3307.       ap->FuncName);
  3308.       for(i = 0; i < ap->NumArgs-1; ++i)
  3309.         DoOutput("(%s), ", ap->Args[i].ArgName);
  3310.       DoOutput("("/*)*/);
  3311.       OutClibType(&cd->Args[i], 0);
  3312.       return DoOutput(/*({((*/") _tags);})\n#endif\n\n");
  3313.     }
  3314.     else
  3315.       return FuncCSTUBS(ap, flags, name);
  3316.       /* call CSTUBS, as this equals the method used there */
  3317.   }
  3318.  
  3319.   if(Flags & FLAG_INLINENEW) /* new style */
  3320.   {
  3321.     STRPTR funcpar = "";
  3322.     DoOutput("#define %s("/*)*/, name);
  3323.  
  3324.     for(i = 0; i < cd->NumArgs; ++i)
  3325.     {
  3326.       if(cd->Args[i].Flags & CPP_FLAG_FUNCTION)
  3327.         funcpar = "FP";
  3328.     }
  3329.  
  3330.     if(ap->NumArgs)
  3331.     {
  3332.       for(i = 0; i < ap->NumArgs-1; ++i)
  3333.         DoOutput("%s, ", ap->Args[i].ArgName);
  3334.       DoOutput("%s", ap->Args[i].ArgName);
  3335.     }
  3336.     DoOutput(/*(*/") \\\n\tLP%ld%s%s%s%s(0x%lx, "/*)*/, ap->NumArgs,
  3337.     (noret ? "NR" : ""), (a45 ? RegNamesUpper[a45] : (STRPTR) ""),
  3338.     (BaseName ? "" : "UB"), funcpar, ap->Bias);
  3339.     if(!noret)
  3340.     {
  3341.       OutClibType(&cd->ReturnType, 0);
  3342.       DoOutput(", ");
  3343.     }
  3344.     DoOutput("%s, ", name);
  3345.  
  3346.     for(i = 0; i < ap->NumArgs; ++i)
  3347.     {
  3348.       j = ap->Args[i].ArgReg;
  3349.       if(a45 && (j == REG_A4 || j == REG_A5))
  3350.         j = REG_D7;
  3351.       if(cd->Args[i].Flags & CPP_FLAG_FUNCTION)
  3352.       {
  3353.         DoOutput("__fpt"); fp = i;
  3354.       }
  3355.       else
  3356.         OutClibType(&cd->Args[i], 0);
  3357.   
  3358.       DoOutput(", %s, %s%s", ap->Args[i].ArgName, RegNames[j],
  3359.       (i == ap->NumArgs-1 && !BaseName ? "" : ", "));
  3360.     }
  3361.  
  3362.     if(BaseName) /* was "##base" used? */
  3363.       DoOutput("\\\n\t, %s_BASE_NAME", ShortBaseNameUpper);
  3364.  
  3365.     if(fp >= 0)
  3366.     {
  3367.       DoOutput(", ");
  3368.       OutClibType(&cd->Args[fp], "__fpt");
  3369.     }
  3370.  
  3371.     if(Flags & FLAG_POWERUP)
  3372.       DoOutput(", IF_CACHEFLUSHALL, NULL, 0, IF_CACHEFLUSHALL, NULL, 0");
  3373.  
  3374.     return DoOutput(/*(*/")\n\n");
  3375.   }
  3376.  
  3377.   /* old mode or stubs mode */
  3378.  
  3379.   DoOutput("%s%s__inline ", Flags & FLAG_INLINESTUB ? "" : "extern ",
  3380.   Flags & FLAG_POWERUP ? "static " : "");
  3381.   OutClibType(&cd->ReturnType, 0);
  3382.   DoOutput("\n%s(%s"/*)*/, name, (BaseName ?
  3383.   (ap->NumArgs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
  3384.  
  3385.   for(i = 0; i < ap->NumArgs; ++i)
  3386.   {
  3387.     OutClibType(&cd->Args[i], ap->Args[i].ArgName);
  3388.     if(i < ap->NumArgs-1)
  3389.       DoOutput(", ");
  3390.   }
  3391.  
  3392.   if(Flags & FLAG_POWERUP)
  3393.   {
  3394.     DoOutput(/*(*/")\n{\n\tstruct Caos MyCaos;\n"/*}*/
  3395.     "\tMyCaos.M68kCacheMode\t= IF_CACHEFLUSHALL;\n"
  3396.     "/*\tMyCaos.M68kStart\t= NULL;\t*/\n"
  3397.     "/*\tMyCaos.M68kSize\t\t= 0;\t*/\n"
  3398.     "\tMyCaos.PPCCacheMode\t= IF_CACHEFLUSHALL;\n"
  3399.     "/*\tMyCaos.PPCStart\t\t= NULL;\t*/\n"
  3400.     "/*\tMyCaos.PPCSize\t\t= 0;\t*/\n");
  3401.  
  3402.     if(ap->NumArgs)
  3403.     {
  3404.       for(i = 0; i < ap->NumArgs; ++i)
  3405.       {
  3406.         DoOutput("\tMyCaos.%s\t\t= (ULONG) %s;\n",
  3407.         RegNames[ap->Args[i].ArgReg], ap->Args[i].ArgName);
  3408.       }
  3409.     }
  3410.  
  3411.     DoOutput("\tMyCaos.caos_Un.Offset\t= %ld;\n", -ap->Bias);
  3412.  
  3413.     if(BaseName)
  3414.       DoOutput("\tMyCaos.a6\t\t= (ULONG) %s_BASE_NAME;\n", ShortBaseNameUpper);
  3415.     if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3416.       DoOutput(/*{*/"\tPPCCallOS(&MyCaos);\n}\n\n");
  3417.     else
  3418.     {
  3419.       DoOutput("\treturn(("/*))*/);
  3420.       OutClibType(&cd->ReturnType, 0);
  3421.       DoOutput(/*{((*/")PPCCallOS(&MyCaos));\n}\n\n");
  3422.     }
  3423.     return Output_Error;
  3424.   }
  3425.  
  3426.   DoOutput(/*(*/")\n{\n%s"/*}*/, (BaseName ? "   BASE_EXT_DECL\n" : ""));
  3427.  
  3428.   if(!noret)
  3429.   {
  3430.     DoOutput("   register ");
  3431.     OutClibType(&cd->ReturnType, "res");
  3432.     DoOutput(" __asm(\"d0\");\n");
  3433.   }
  3434.  
  3435.   if(BaseName)
  3436.     DoOutput("   register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
  3437.     GetBaseType());
  3438.  
  3439.   for(i = 0; i < ap->NumArgs; ++i)
  3440.   {
  3441.     j = ap->Args[i].ArgReg;
  3442.     if(a45 && (j == REG_A4 || j == REG_A5))
  3443.       j = REG_D7;
  3444.  
  3445.     DoOutput("   register ");
  3446.     OutClibType(&cd->Args[i], RegNames[j]);
  3447.     DoOutput(" __asm(\"%s\") = %s;\n", RegNames[j], ap->Args[i].ArgName);
  3448.   }
  3449.  
  3450.   if(a45)
  3451.   {
  3452.     DoOutput("   __asm volatile (\"exg d7,%s\\n\\t"/*)*/
  3453.     "jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", RegNames[a45],
  3454.     ap->Bias, RegNames[a45]);
  3455.   }
  3456.   else
  3457.     DoOutput("   __asm volatile (\"jsr a6@(-0x%lx:W)\"\n"/*)*/, ap->Bias);
  3458.  
  3459.   DoOutput(noret ? "   : /* No Output */\n" : "   : \"=r\" (res)\n");
  3460.  
  3461.   DoOutput("   : ");
  3462.   if(BaseName)
  3463.     DoOutput("\"r\" (a6)%s", (ap->NumArgs ? ", ": ""));
  3464.  
  3465.   for(i = 0; i < ap->NumArgs; ++i)
  3466.   {
  3467.     j = ap->Args[i].ArgReg;
  3468.     if(a45 && (j == REG_A4 || j == REG_A5))
  3469.       j = REG_D7;
  3470.  
  3471.     DoOutput("\"r\" (%s)%s", RegNames[j], (i < ap->NumArgs-1 ? ", " : ""));
  3472.   }
  3473.  
  3474.   DoOutput("\n   : \"d0\", \"d1\", \"a0\", \"a1\", \"fp0\", \"fp1\"");
  3475.  
  3476.   if(noret)
  3477.     return DoOutput(/*({*/", \"cc\", \"memory\");\n}\n\n");
  3478.   else
  3479.     return DoOutput(/*({*/", \"cc\", \"memory\");\n   return res;\n}\n\n");
  3480. }
  3481.  
  3482. ULONG FuncPowerUP(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3483. {
  3484.   ULONG i;
  3485.   struct ClibData *cd;
  3486.  
  3487.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  3488.     return 1;
  3489.  
  3490.   Flags |= FLAG_DONE; /* We did something */
  3491.  
  3492.   if(flags & FUNCFLAG_ALIAS)
  3493.   {
  3494.     if(flags & FUNCFLAG_TAG)
  3495.       return DoOutput("#ifndef NO_PPCINLINE_STDARG\n#define %s %s\n#endif\n\n", name, ap->TagName);
  3496.  
  3497.     DoOutput("#define %s("/*)*/, name);
  3498.     for(i = 0; i < ap->NumArgs-1; ++i)
  3499.       DoOutput("%s, ", ap->Args[i].ArgName);
  3500.     DoOutput(/*(*/"%s) %s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
  3501.     for(i = 0; i < ap->NumArgs-1; ++i)
  3502.       DoOutput("(%s), ", ap->Args[i].ArgName);
  3503.     return DoOutput(/*(*/"(%s))\n\n", ap->Args[i].ArgName);
  3504.   }
  3505.  
  3506.   if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  3507.     return 1;
  3508.  
  3509.   if(flags & FUNCFLAG_TAG)
  3510.   {
  3511.     DoOutput("#ifndef NO_PPCINLINE_STDARG\n#define %s("/*)*/, name);
  3512.     for(i = 0; i < ap->NumArgs-1; ++i)
  3513.       DoOutput("%s, ", ap->Args[i].ArgName);
  3514.     DoOutput(/*(*/"tags...) \\\n\t({ULONG _tags[] = {tags}; %s("/*)})*/,
  3515.     ap->FuncName);
  3516.     for(i = 0; i < ap->NumArgs-1; ++i)
  3517.       DoOutput("(%s), ", ap->Args[i].ArgName);
  3518.     DoOutput("("/*)*/);
  3519.     OutClibType(&cd->Args[i], 0);
  3520.     return DoOutput(/*({((*/") _tags);})\n#endif\n\n");
  3521.   }
  3522.  
  3523.   DoOutput("#define\t%s("/*)*/, name);
  3524.  
  3525.   if(ap->NumArgs)
  3526.   {
  3527.   
  3528.     for(i = 0; i < ap->NumArgs-1; ++i)
  3529.       DoOutput("%s, ", ap->Args[i].ArgName);
  3530.     DoOutput(/*(*/"%s)\t_%s("/*)*/, ap->Args[i].ArgName, name);
  3531.  
  3532.     if(BaseName)
  3533.       DoOutput("%s_BASE_NAME, ", ShortBaseNameUpper);
  3534.  
  3535.     for(i = 0; i < ap->NumArgs-1; ++i)
  3536.       DoOutput("%s, ", ap->Args[i].ArgName);
  3537.     DoOutput(/*(*/"%s)\n\n", ap->Args[i].ArgName);
  3538.   }
  3539.   else if(BaseName)
  3540.     DoOutput(/*(*/")\t_%s(%s_BASE_NAME)\n\n", name, ShortBaseNameUpper);
  3541.   else
  3542.     DoOutput(/*(*/")\t_%s()\n\n", name);
  3543.  
  3544.   DoOutput("static __inline ");
  3545.   OutClibType(&cd->ReturnType, 0);
  3546.   
  3547.   DoOutput("\n_%s("/*)*/, name);
  3548.   if(BaseName)
  3549.     DoOutput("void * %s%s", BaseName, ap->NumArgs ? ", " : "");
  3550.  
  3551.   for(i = 0; i < ap->NumArgs; ++i)
  3552.   {
  3553.     OutClibType(&cd->Args[i], ap->Args[i].ArgName);
  3554.     if(i < ap->NumArgs-1)
  3555.       DoOutput(", ");
  3556.   }
  3557.  
  3558.   DoOutput(/*(*/")\n{\n\tstruct Caos MyCaos;\n"/*}*/
  3559.   "\tMyCaos.M68kCacheMode\t= IF_CACHEFLUSHALL;\n"
  3560.   "/*\tMyCaos.M68kStart\t= NULL;\t*/\n"
  3561.   "/*\tMyCaos.M68kSize\t\t= 0;\t*/\n"
  3562.   "\tMyCaos.PPCCacheMode\t= IF_CACHEFLUSHALL;\n"
  3563.   "/*\tMyCaos.PPCStart\t\t= NULL;\t*/\n"
  3564.   "/*\tMyCaos.PPCSize\t\t= 0;\t*/\n");
  3565.  
  3566.   if(ap->NumArgs)
  3567.   {
  3568.     for(i = 0; i < ap->NumArgs; ++i)
  3569.     {
  3570.       DoOutput("\tMyCaos.%s\t\t= (ULONG) %s;\n",
  3571.       RegNames[ap->Args[i].ArgReg], ap->Args[i].ArgName);
  3572.     }
  3573.   }
  3574.  
  3575.   DoOutput("\tMyCaos.caos_Un.Offset\t= %ld;\n", -ap->Bias);
  3576.  
  3577.   if(BaseName)
  3578.     DoOutput("\tMyCaos.a6\t\t= (ULONG) %s;\n", BaseName);
  3579.   if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3580.     DoOutput(/*{*/"\tPPCCallOS(&MyCaos);\n}\n\n");
  3581.   else
  3582.   {
  3583.     DoOutput("\treturn(("/*))*/);
  3584.     OutClibType(&cd->ReturnType, 0);
  3585.     DoOutput(/*{((*/")PPCCallOS(&MyCaos));\n}\n\n");
  3586.   }
  3587.   return Output_Error;
  3588. }
  3589.  
  3590. ULONG FuncFPCUnit(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3591. {
  3592.   LONG i;
  3593.   struct ClibData *cd;
  3594.  
  3595.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
  3596.     return 1;
  3597.   else if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  3598.     return 1;
  3599.  
  3600.   if(!FuncFPCType(ap, flags, name))
  3601.     return 0;
  3602.  
  3603.   DoOutput("BEGIN\n  ASM\n\tMOVE.L\tA6,-(A7)\n");
  3604.  
  3605.   for(i = 0; i < ap->NumArgs; ++i)
  3606.     DoOutput("\tMOVE%s.L\t%s,%s\n", ap->Args[i].ArgReg >= REG_A0 ? "A" : "",
  3607.     ap->Args[i].ArgName, RegNamesUpper[ap->Args[i].ArgReg]);
  3608.  
  3609.   if(BaseName)
  3610.     DoOutput("\tMOVEA.L\t%s,A6\n", BaseName);
  3611.   DoOutput("\tJSR\t-%03ld(A6)\n\tMOVEA.L\t(A7)+,A6\n", ap->Bias);
  3612.  
  3613.   if(!IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3614.   {
  3615.     if(!cd->ReturnType.PointerDepth &&
  3616.     cd->ReturnType.Flags == CPP_FLAG_BOOLEAN)
  3617.       DoOutput("\tTST.W\tD0\n\tBEQ.B\t@end\n\tMOVEQ\t#1,D0\n"
  3618.       "  @end:\tMOVE.B\tD0,@RESULT\n");
  3619.     else
  3620.       DoOutput("\tMOVE.L\tD0,@RESULT\n");
  3621.   }
  3622.   return DoOutput("  END;\nEND;\n\n");
  3623. }
  3624.  
  3625. ULONG FuncFPCType(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3626. {
  3627.   ULONG ret = 1;
  3628.   LONG i;
  3629.   struct ClibData *cd;
  3630.  
  3631.   if(CheckError(ap, AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
  3632.     return 1;
  3633.   else if(!(cd = GetClibFunc(ap->FuncName, ap, flags)))
  3634.     return 1;
  3635.  
  3636.   if(IsCPPType(&cd->ReturnType, CPP_TYPE_VOID))
  3637.   {
  3638.     ret = 0; DoOutput("PROCEDURE %s", name);
  3639.   }
  3640.   else
  3641.     DoOutput("FUNCTION %s", name);
  3642.  
  3643.   if(ap->NumArgs)
  3644.   {
  3645.     DoOutput("("/*)*/);
  3646.     for(i = 0; i < ap->NumArgs;)
  3647.     {
  3648.       OutPASCALType(&cd->Args[i], ap->Args[i].ArgName, 0);
  3649.       if(++i != ap->NumArgs)
  3650.         DoOutput("; ");
  3651.     }
  3652.     DoOutput(/*(*/")");
  3653.   }
  3654.  
  3655.   if(ret)
  3656.     OutPASCALType(&cd->ReturnType, "", 1);
  3657.  
  3658.   Flags |= FLAG_DONE; /* We did something */
  3659.  
  3660.   return DoOutput(";\n");
  3661. }
  3662.  
  3663. ULONG FuncBMAP(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3664. {
  3665.   UBYTE reg, i;
  3666.  
  3667.   if(CheckError(ap, AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_A6USE|AMIPRAGFLAG_A5USE|AMIPRAGFLAG_PPC))
  3668.     return 1;
  3669.  
  3670.   Flags |= FLAG_DONE; /* We did something */
  3671.  
  3672.   for(i = 0; BMAPSpecial[i]; ++i)
  3673.   {
  3674.     if(!stricmp(name, BMAPSpecial[i]))
  3675.     {
  3676.       DoOutput("x"); break;
  3677.     }
  3678.   }
  3679.  
  3680.   DoOutput(name);
  3681.   reg = 0;                      DoOutputDirect(®, 1);
  3682.   reg = (-ap->Bias)>>8;         DoOutputDirect(®, 1);
  3683.   reg = -ap->Bias;              DoOutputDirect(®, 1);
  3684.   for(i = 0; i < ap->NumArgs; ++i)
  3685.   {
  3686.     reg = 1+ap->Args[i].ArgReg; DoOutputDirect(®, 1);
  3687.   }
  3688.   reg = 0;
  3689.   return DoOutputDirect(®, 1);
  3690. }
  3691.  
  3692. ULONG FuncVBCCInline(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3693. {
  3694.   struct ClibData *cd;
  3695.   STRPTR c1, c2;
  3696.   ULONG i;
  3697.  
  3698.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_PPC))
  3699.     return 1;
  3700.  
  3701.   if(!(cd = GetClibFunc(name, ap, flags)))
  3702.     return 1;
  3703.  
  3704.   c1 = Flags & FLAG_NEWSYNTAX ? "(" : ""; /*)*/
  3705.   c2 = Flags & FLAG_NEWSYNTAX ? "," : "("; /*)*/
  3706.  
  3707.   Flags |= FLAG_DONE; /* We did something */
  3708.  
  3709.   if(flags & FUNCFLAG_ALIAS)
  3710.   {
  3711.     DoOutput("#define %s("/*)*/, name);
  3712.     for(i = 0; i < ap->NumArgs-1; ++i)
  3713.       DoOutput("%s, ", ap->Args[i].ArgName);
  3714.     DoOutput(/*(*/"%s) __%s("/*)*/, ap->Args[i].ArgName, ap->FuncName);
  3715.     for(i = 0; i < ap->NumArgs; ++i)
  3716.       DoOutput("(%s), ", ap->Args[i].ArgName);
  3717.     return DoOutput(/*(*/"%s)\n\n", BaseName);
  3718.   }
  3719.  
  3720.   OutClibType(&cd->ReturnType, 0);
  3721.   DoOutput(" __%s("/*)*/, name);
  3722.  
  3723.   for(i = 0; i < ap->NumArgs; ++i)
  3724.   {
  3725.     DoOutput("__reg(\"%s\") ", RegNames[ap->Args[i].ArgReg]);
  3726.     OutClibType(&cd->Args[i], ap->Args[i].ArgName);
  3727.     if(i < ap->NumArgs-1)
  3728.       DoOutput(", ");
  3729.   }
  3730.  
  3731.   if(BaseName)
  3732.   {
  3733.     if(ap->NumArgs)
  3734.       DoOutput(", ");
  3735.     DoOutput("__reg(\"a6\") void *");
  3736.   }
  3737.   DoOutput(/*((*/")=\"\\tJSR\\t%s-%ld%sA6)\";\n", c1, ap->Bias, c2);
  3738.   DoOutput("#define %s("/*)*/, name);
  3739.   for(i = 0; i < ap->NumArgs; ++i)
  3740.   {
  3741.     DoOutput("%s", ap->Args[i].ArgName);
  3742.     if(i < ap->NumArgs-1)
  3743.       DoOutput(", ");
  3744.   }
  3745.   DoOutput(/*(*/") __%s("/*)*/, name);
  3746.   for(i = 0; i < ap->NumArgs; ++i)
  3747.   {
  3748.     DoOutput("(%s)", ap->Args[i].ArgName);
  3749.     if(i < ap->NumArgs-1)
  3750.       DoOutput(", ");
  3751.   }
  3752.   if(BaseName)
  3753.   {
  3754.     if(ap->NumArgs)
  3755.       DoOutput(", ");
  3756.     DoOutput("%s", BaseName);
  3757.   }
  3758.  
  3759.   return DoOutput(/*(*/")\n\n");
  3760. }
  3761.  
  3762. ULONG FuncVBCCWOSText(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3763. {
  3764.   ULONG i, k, count, ofs;
  3765.   struct ClibData *cd = 0;
  3766.  
  3767.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG))
  3768.     return 1;
  3769.  
  3770.   if((flags & FUNCFLAG_TAG) && !(ap->Flags & AMIPRAGFLAG_PPC) &&!(cd = GetClibFunc(name, ap, flags)))
  3771.     return 1;
  3772.  
  3773.   if((ap->Flags & AMIPRAGFLAG_PPC) && !BaseName &&
  3774.   ((ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2)) || !(Flags & FLAG_WOSLIBBASE)))
  3775.   {
  3776.     DoError(ERR_MISSING_BASENAME, ap->Line);
  3777.     return 1;
  3778.   }
  3779.  
  3780.   Flags |= FLAG_DONE;
  3781.  
  3782.   if(Flags & FLAG_ASMSECTION)
  3783.     DoOutput("\t.section %s,\"cr\"\n", name);
  3784.  
  3785.   DoOutput("\t.text\n\t.align\t3\n");
  3786.   if(Flags & FLAG_WOSLIBBASE)  /* PPCBase already in r3, LibBase in r4 */
  3787.   {
  3788.     if(ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2))
  3789.       DoOutput("\t.extern _%s\n", BaseName);
  3790.     DoOutput("\t.global __%s\n__%s:\n", name, name);
  3791.   }
  3792.   else
  3793.   {
  3794.     if(BaseName)
  3795.       DoOutput("\t.extern _%s\n", BaseName);
  3796.     if(!(ap->Flags & AMIPRAGFLAG_PPC))
  3797.       DoOutput("\t.extern _PowerPCBase\n");
  3798.     DoOutput("\t.global _%s\n_%s:\n", name, name);
  3799.   }
  3800.  
  3801.   if(ap->Flags & AMIPRAGFLAG_PPC2)
  3802.   {
  3803.     DoOutput("\tstw\tr2,20(r1)\n\tmflr\tr0\n\tstw\tr0,16(r1)\n"
  3804.     "\tlwz\tr2,_%s(r2)\n\tlwz\tr0,-%ld(r2)\n\tmtlr\tr0\n\tblrl\n"
  3805.     "\tlwz\tr0,16(r1)\n\tlwz\tr2,20(r1)\n\tmtlr\tr0\n\tblr\n",
  3806.     BaseName,ap->Bias-2);
  3807.   }
  3808.   else if(ap->Flags & AMIPRAGFLAG_PPC0)
  3809.   {
  3810.     DoOutput("\tlwz\tr11,_%s(r2)\n\tlwz\tr0,-%ld(r11)\n\tmtlr\tr0\n\tblrl\n",
  3811.     BaseName,ap->Bias-2);
  3812.   }
  3813.   else if(ap->Flags & AMIPRAGFLAG_PPC)
  3814.   {
  3815.     count = ap->NumArgs;
  3816.     if(Flags & FLAG_WOSLIBBASE)    /* LibBase already in r3 */
  3817.     {
  3818.       /* init stack frame */
  3819.       i = (count <= 8) ? 32 : ((56+(count-8)*8+15)&~15); /* stksize */
  3820.       DoOutput("\tmflr\tr0\n\tstw\tr0,8(r1)\n\tstwu\tr1,-%ld(r1)\n",i);
  3821.  
  3822.       if(count > 8)
  3823.       {
  3824.         /* extra arguments must be passed on the stack */
  3825.         k = 32-(count-8); /* firstreg */
  3826.  
  3827.         DoOutput("\tstmw\tr%ld,%ld(r1)\n\tlmw\tr%ld,%ld(r1)\n",
  3828.     k, 56+(count-8)*4,k,i+56);
  3829.         if(flags & FUNCFLAG_TAG)
  3830.           DoOutput("\taddi\tr31,r1,%ld\n", i+20+count*4);
  3831.         DoOutput("\tstmw\tr%ld,56(r1)\n",k);
  3832.       }
  3833.       else if(flags & FUNCFLAG_TAG)
  3834.       {
  3835.         DoOutput("\taddi\tr%ld,r1,%ld\n", count+3, i+20+count*4);
  3836.         --count;
  3837.       }
  3838.     }
  3839.     else    /* Args must be shifted! */
  3840.     {
  3841.       /* init stack frame */
  3842.       i = (count < 8) ? 32 : ((56+(count-7)*8+15)&~15); /* stksize */
  3843.       DoOutput("\tmflr\tr0\n\tstw\tr0,8(r1)\n\tstwu\tr1,-%ld(r1)\n", i);
  3844.  
  3845.       if(count > 7)
  3846.       {
  3847.         /* extra arguments must be passed on the stack */
  3848.         if(count == 8)
  3849.         {
  3850.           /* special case: move 8th argument into stack frame */
  3851.           if(flags & FUNCFLAG_TAG)
  3852.             DoOutput("\taddi\tr10,r1,%ld\n",i+20+count*4);
  3853.           DoOutput("\tstw\tr10,56(r1)\n");
  3854.         }
  3855.         else
  3856.         {
  3857.           k = 32-(count-7); /* firstreg */
  3858.  
  3859.           DoOutput("\tstmw\tr%ld,%ld(r1)\n\tmr\tr%ld,r10\n"
  3860.       "\tlmw\tr%ld,%ld(r1)\n", k, 56+(count-7)*4, k, k+1, i+56);
  3861.           if(flags & FUNCFLAG_TAG)
  3862.             DoOutput("\taddi\tr31,r1,%ld\n", i+20+count*4);
  3863.           DoOutput("\tstmw\tr%ld,56(r1)\n",k);
  3864.         }
  3865.       }
  3866.       else if(flags & FUNCFLAG_TAG)
  3867.       {
  3868.         DoOutput("\taddi\tr%ld,r1,%ld\n", count+3, i+20+count*4);
  3869.         --count;
  3870.       }
  3871.  
  3872.       /* shift all arguments into their following register */
  3873.       for(k=(count<8)?count:7; k > 0; --k)
  3874.         DoOutput("\tmr\tr%ld,r%ld\n", 3+k, 2+k);
  3875.  
  3876.       /* load library base and LVO, then call LVO via LR */
  3877.       DoOutput("\tlwz\tr3,_%s(r2)\n",BaseName);
  3878.     }
  3879.  
  3880.     /* call LVO */
  3881.     DoOutput("\tlwz\tr0,-%ld(r3)\n\tmtlr\tr0\n\tblrl\n", ap->Bias-2);
  3882.  
  3883.     /* cleanup stack frame and return */
  3884.     if(count > 8)
  3885.     {
  3886.       k = Flags & FLAG_WOSLIBBASE ? 8 : 7;    /* restore saved regs */
  3887.       DoOutput("\tlmw\tr%ld,%ld(r1)\n", 32-(count-k),56+(count-k)*4);
  3888.     }
  3889.     DoOutput("\taddi\tr1,r1,%ld\n\tlwz\tr0,8(r1)\n\tmtlr\tr0\n\tblr\n");
  3890.   }
  3891.   else
  3892.   {
  3893.     DoOutput("\tmflr\tr0\n\tstw\tr0,8(r1)\n\tstwu\tr1,-0xB0(r1)\n");
  3894.  
  3895.     /* clear PP_Flags, PP_Stack and PP_StackSize */
  3896.     DoOutput("\tli\tr11,0\n\tstw\tr11,0x28(r1)\n\tstw\tr11,0x2C(r1)\n"
  3897.     "\tstw\tr11,0x30(r1)\n");
  3898.  
  3899.     if(Flags & FLAG_WOSLIBBASE)
  3900.       DoOutput("\tli\tr11,-%ld\n\tstw\tr4,0x20(r1)\n\tstw\tr11,0x24(r1)\n"
  3901.       "\tstw\tr4,0x6C(r1)\n",ap->Bias);
  3902.     else if(!BaseName)
  3903.       DoOutput("\tli\tr11,-%ld\n\tstw\tr11,0x24(r1)\n",ap->Bias);
  3904.     else
  3905.       DoOutput("\tlwz\tr0,_%s(r2)\n\tli\tr11,-%ld\n"
  3906.       "\tstw\tr0,0x20(r1)\n\tstw\tr11,0x24(r1)\n\tstw\tr0,0x6c(r1)\n",
  3907.       BaseName,ap->Bias);
  3908.  
  3909.     ofs = Flags & FLAG_WOSLIBBASE ? 2 : 0;
  3910.     k = ap->NumArgs - (flags & FUNCFLAG_TAG ? 1 : 0);
  3911.     for(i = 0; i < k; ++i)
  3912.     {
  3913.       if(i + ofs <= 7)
  3914.       {
  3915.         if(ap->Args[i].ArgReg == REG_A6)
  3916.           DoOutput("\tstw\tr%ld,0x20(r1)\n",i+3+ofs);
  3917.         DoOutput("\tstw\tr%ld,",i+3+ofs);
  3918.       }
  3919.       else
  3920.       {
  3921.         DoOutput("\tlwz\tr11,%ld(r1)\n",(i+1+ofs)*4+196);
  3922.         if(ap->Args[i].ArgReg == REG_A6)
  3923.           DoOutput("\tstw\tr11,0x20(r1)\n");
  3924.         DoOutput("\tstw\tr11,");
  3925.       }
  3926.       DoOutput("%ld(r1)\n", 0x34+4*ap->Args[i].ArgReg);
  3927.     }
  3928.     if(flags & FUNCFLAG_TAG)
  3929.     {
  3930.       if((i+ofs) <= 7 && cd->Args[i].Type != CPP_TYPE_VARARGS)
  3931.         DoOutput("\tstw\tr%ld,%ld(r1)\n",i+3+ofs, 0xC4+(ap->NumArgs+ofs)*4);
  3932.       DoOutput("\taddi\tr11,r1,%ld\n\tstw\tr11,", 0xC4+(ap->NumArgs+ofs)*4);
  3933.       DoOutput("%ld(r1)\n", 0x34+4*ap->Args[i].ArgReg);
  3934.     }
  3935.  
  3936.     if(!(Flags & FLAG_WOSLIBBASE))
  3937.       DoOutput("\tlwz\tr3,_PowerPCBase(r2)\n");
  3938.  
  3939.     DoOutput("\taddi\tr4,r1,0x20\n\tlwz\tr0,-298(r3)\n\tmtlr\tr0\n\tblrl\n"
  3940.     "\tlwz\tr3,0x34(r1)\n\taddi\tr1,r1,0xB0\n\tlwz\tr0,8(r1)\n\tmtlr\tr0\n\tblr\n");
  3941.   }
  3942.  
  3943.   if(Flags & FLAG_WOSLIBBASE)
  3944.     return DoOutput("\t.type\t__%s,@function\n\t.size\t__%s,$-__%s\n\n",
  3945.     name, name, name);
  3946.   else
  3947.     return DoOutput("\t.type\t_%s,@function\n\t.size\t_%s,$-_%s\n\n",
  3948.     name, name, name);
  3949. }
  3950.  
  3951. ULONG FuncVBCCWOSCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
  3952. {
  3953.   ULONG i, j = 0, k, l = 0, ofs, pos, count;
  3954.   ULONG *data;
  3955.   struct ClibData *cd = 0;
  3956.  
  3957.   data = (ULONG *) tempbuf;
  3958.  
  3959.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG))
  3960.     return 1;
  3961.  
  3962.   if((flags & FUNCFLAG_TAG) && !(ap->Flags & AMIPRAGFLAG_PPC) && !(cd = GetClibFunc(name, ap, flags)))
  3963.     return 1;
  3964.  
  3965.   if((ap->Flags & AMIPRAGFLAG_PPC) && !BaseName &&
  3966.   ((ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2)) || !(Flags & FLAG_WOSLIBBASE)))
  3967.   {
  3968.     DoError(ERR_MISSING_BASENAME, ap->Line);
  3969.     return 1;
  3970.   }
  3971.  
  3972.   Flags |= FLAG_DONE; /* We did something */
  3973.  
  3974.   if(Flags & FLAG_WOSLIBBASE)
  3975.   {
  3976.     i = strlen(name)+1;
  3977.     data[0] = HUNK_UNIT; data[1] = (i + 3)>>2;
  3978.   
  3979.     DoOutputDirect(data, 8);
  3980.     DoOutputDirect("_", 1);
  3981.     DoOutputDirect(name, i-1);
  3982.   }
  3983.   else
  3984.   {
  3985.     i = strlen(name);
  3986.     data[0] = HUNK_UNIT; data[1] = (i + 3)>>2;
  3987.   
  3988.     DoOutputDirect(data, 8);
  3989.     DoOutputDirect(name, i);
  3990.   }
  3991.   DoOutputDirect("\0\0\0", (data[1]<<2)-i);
  3992.  
  3993.   data[0] = HUNK_NAME;
  3994.   data[1] = 2;
  3995.   DoOutputDirect(data, 8);
  3996.   DoOutputDirect(".text\0\0\0", 8);
  3997.  
  3998.   data[0] = HUNK_PPC_CODE;
  3999.  
  4000.   pos = 2;
  4001.  
  4002.   if(ap->Flags & AMIPRAGFLAG_PPC2)
  4003.   {
  4004.     data[pos++] = 0x90410014; /* stw r2,20(r1) */
  4005.     data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
  4006.     data[pos++] = 0x90010010; /* stw r0,16(r1) */
  4007.     l = pos-2;
  4008.     data[pos++] = 0x80420000; /* lwz r2,BaseName(r2) */
  4009.     data[pos++] = 0x80030000 - ap->Bias; /* lwz r0,-ap->Bias(r2) */
  4010.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
  4011.     data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
  4012.     data[pos++] = 0x80010010; /* lwz r0,16(r1) */
  4013.     data[pos++] = 0x80410014; /* lwz r2,20(r1) */
  4014.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
  4015.     data[pos++] = 0x4E800020; /* blr = bclr 20,0 = jump */
  4016.   }
  4017.   else if(ap->Flags & AMIPRAGFLAG_PPC0)
  4018.   {
  4019.     l = pos-2;
  4020.     data[pos++] = 0x81620000; /* lwz r11,BaseName(r2) */
  4021.     data[pos++] = 0x800C0000 - ap->Bias; /* lwz r0,-ap->Bias(r11) */
  4022.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = store link register */
  4023.     data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
  4024.   }
  4025.   else if(ap->Flags & AMIPRAGFLAG_PPC)
  4026.   {
  4027.     count = ap->NumArgs;
  4028.     if(Flags & FLAG_WOSLIBBASE)    /* LibBase already in r3 */
  4029.     {
  4030.       /* init stack frame */
  4031.       i = (count <= 8) ? 32 : ((56+(count-8)*8+15)&~15); /* stksize */
  4032.       data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
  4033.       data[pos++] = 0x90010008; /* stw r0,8(r1) */
  4034.       data[pos++] = 0x94220000 - i; /* stwu r1,-i(r1) */
  4035.  
  4036.       if(count > 8)
  4037.       {
  4038.         /* extra arguments must be passed on the stack */
  4039.         k = 32-(count-8); /* firstreg */
  4040.     data[pos++] = 0xBC010000 + (k << 21) + (56+(count-8)*4); /* stmw rk,X(r1) */
  4041.     data[pos++] = 0xB8010000 + (k << 21) + (i+56); /* lmw rk,Y(r1) */
  4042.         if(flags & FUNCFLAG_TAG)
  4043.           data[pos++] = 0x3BE10000 + (i+20+count*4); /* addi r31,r1,X */
  4044.         data[pos++] = 0xBC010038 + (k << 21); /* stmw rk,56(r1) */
  4045.       }
  4046.       else if(flags & FUNCFLAG_TAG)
  4047.       {
  4048.         data[pos++] = 0x38010000 + ((count+3)<<21) + (i+20+count*4); /* addi rX,r1,Y */
  4049.         --count;
  4050.       }
  4051.     }
  4052.     else    /* Args must be shifted! */
  4053.     {
  4054.       /* init stack frame */
  4055.       i = (count < 8) ? 32 : ((56+(count-7)*8+15)&~15); /* stksize */
  4056.       data[pos++] = 0x7C0802A6; /* mflr r0 = mfspr r0,8 = get link register */
  4057.       data[pos++] = 0x90010008; /* stw r0,8(r1) */
  4058.       data[pos++] = 0x94220000 - i; /* stwu r1,-i(r1) */
  4059.  
  4060.       if(count > 7)
  4061.       {
  4062.         /* extra arguments must be passed on the stack */
  4063.         if(count == 8)
  4064.         {
  4065.           /* special case: move 8th argument into stack frame */
  4066.           if(flags & FUNCFLAG_TAG)
  4067.             data[pos++] = 0x39410000 + (i+20+count*4); /* addi r10,r1,X */
  4068.           data[pos++] = 0x91410038; /* stw r10,56(r1) */
  4069.         }
  4070.         else
  4071.         {
  4072.           k = 32-(count-7); /* firstreg */
  4073.  
  4074.       data[pos++] = 0xBC010000 + (k << 21) + (56+(count-7)*4); /* stmw rk,X(r1) */
  4075.           data[pos++] = 0x7D405378 + (k<<16); /* mr rk,r10 = or rk,r10,r10 */
  4076.       data[pos++] = 0xB8010000 + ((k+1) << 21) + (i+56); /* lmw rk,Y(r1) */
  4077.           if(flags & FUNCFLAG_TAG)
  4078.             data[pos++] = 0x3BE10000 + (i+20+count*4); /* addi r31,r1,X */
  4079.           data[pos++] = 0xBC010038 + (k << 21); /* stmw rk,56(r1) */
  4080.         }
  4081.       }
  4082.       else if(flags & FUNCFLAG_TAG)
  4083.       {
  4084.         data[pos++] = 0x38010000 + ((count+3)<<21) + (i+20+count*4); /* addi rX,r1,Y */
  4085.         --count;
  4086.       }
  4087.  
  4088.       /* shift all arguments into their following register */
  4089.       for(k=(count<8)?count:7; k > 0; --k)
  4090.         data[pos++] = 0x7C000378 + ((3+k)<<16) + ((2+k)<<21) + ((2+k)<<11); /* mr rX,rY = or rX,rY,rY */
  4091.  
  4092.       /* load library base and LVO, then call LVO via LR */
  4093.       l = pos-2;
  4094.       data[pos++] =0x80620000; /* lwz r3,BaseName(r2) */
  4095.     }
  4096.     /* call LVO */
  4097.     data[pos++] = 0x80040000 - (ap->Bias-2); /* lwz r0,-(ap->Bias-2)(r3) */
  4098.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
  4099.     data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
  4100.  
  4101.  
  4102.     /* cleanup stack frame and return */
  4103.     if(count > 8)
  4104.     {
  4105.       k = Flags & FLAG_WOSLIBBASE ? 8 : 7;    /* restore saved regs */
  4106.       data[pos++] = 0xB8010000 + ((32-(count-k))<<21) + (56+(count-k)*4); /* lmw rX,Y(r1) */
  4107.     }
  4108.     data[pos++] = 0x38210000 + i; /* addi r1,r1,i */
  4109.     data[pos++] = 0x80010008; /* lwz r0,8(r1) */
  4110.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
  4111.     data[pos++] = 0x4E800020; /* blr = bclr 20,0 = jump */
  4112.   }
  4113.   else
  4114.   {
  4115.     data[pos++] = 0x7C0802A6;  /* mflr r0 = mfspr r0,8 = get link register */
  4116.     data[pos++] = 0x90010008;  /* stw r0,8(r1) = save link register in 8(r1) */
  4117.     data[pos++] = 0x9421FF50;  /* stwu r1,-0xB0(r1) = store word from r1 in -0xB0(r1) and update r1 */
  4118.  
  4119.     data[pos++] = 0x39600000;  /* li r11,0 = addi r11,r0,0 = clear r11 */
  4120.     data[pos++] = 0x91610028;  /* stwu r11,0x28(r1) = clear PP_Flags */
  4121.     data[pos++] = 0x9161002C;  /* stwu r11,0x2C(r1) = clear PP_Stack */
  4122.     data[pos++] = 0x91610030;  /* stwu r11,0x30(r1) = clear PP_StackSize */
  4123.  
  4124.     if(Flags & FLAG_WOSLIBBASE)
  4125.     {
  4126.       data[pos++] = 0x39610000 - ap->Bias; /* li r11,ap->Bias */
  4127.       data[pos++] = 0x90810020; /* stw r4,0x20(r1) = set PP_Code to Librarybase */
  4128.       data[pos++] = 0x91610024; /* stw r11,0x24(r1) = set PP_Offset to Bias value */
  4129.       data[pos++] = 0x9081006C; /* stw r4,0x6C(r1) = set A6 register */
  4130.     }
  4131.     else if(!BaseName)
  4132.     {
  4133.       data[pos++] = 0x39610000 -ap->Bias; /* li r11,ap->Bias */
  4134.       data[pos++] = 0x91610024; /* stw r11,0x24(r1) = set PP_Offset to Bias value */
  4135.     }
  4136.     else
  4137.     {
  4138.       l = pos-2;
  4139.       data[pos++] = 0x80020000; /* lwz r0,BaseName(r2)  --> 16BIT RELOC! */
  4140.       data[pos++] = 0x39610000 - ap->Bias; /* li r11,ap->Bias */
  4141.       data[pos++] = 0x90010020; /* stw r0,0x20(r1) = set PP_Code to Librarybase */
  4142.       data[pos++] = 0x91610024; /* stw r11,0x24(r1) = set PP_Offset to Bias value */
  4143.       data[pos++] = 0x9001006C; /* stw r4,0x6C(r1) = set A6 register */
  4144.     }
  4145.   
  4146.     ofs = Flags & FLAG_WOSLIBBASE ? 2 : 0;
  4147.     k = ap->NumArgs - (flags & FUNCFLAG_TAG ? 1 : 0);
  4148.     for(i = 0; i < k; ++i)
  4149.     {
  4150.       j = 0x34+4*ap->Args[i].ArgReg; /* PP_Regs offset */
  4151.       if(i + ofs <= 7)
  4152.       {
  4153.         if(ap->Args[i].ArgReg == REG_A6)
  4154.           data[pos++] = 0x90010020 + ((i+3+ofs)<<21); /* stw rX,0x20(r1) */
  4155.         data[pos++] = 0x90010000 + ((i+3+ofs)<<21) + j; /* stw rX,j(r1) */
  4156.       }
  4157.       else
  4158.       {
  4159.         data[pos++] = 0x81610000 + ((i+1+ofs)*4+0xC4); /* lwz r11,X(r1) = get data from stack */
  4160.         if(ap->Args[i].ArgReg == REG_A6)
  4161.           data[pos++] = 0x91610020; /* stw r11,0x20(r1) */
  4162.         data[pos++] = 0x91610000 + j; /* stw r11,j(r1) */
  4163.       }
  4164.     }
  4165.     if(flags & FUNCFLAG_TAG)
  4166.     {
  4167.       j = (ap->NumArgs+ofs)*4+0xC4;
  4168.  
  4169.       if((i+ofs) <= 7 && cd->Args[i].Type != CPP_TYPE_VARARGS)
  4170.         data[pos++] = 0x90010000 + ((i+3+ofs)<<21) + j; /* stw rX,j(r1) */
  4171.       data[pos++] = 0x39610000 + j; /* addi r11,r1,j */
  4172.       data[pos++] = 0x91610000 + (0x34+4*ap->Args[i].ArgReg); /* stw r11,X(r1) */
  4173.     }
  4174.  
  4175.     if(!(Flags & FLAG_WOSLIBBASE))
  4176.     {
  4177.       j = pos - 2; /* store 16BIT reloc offset */
  4178.       data[pos++] = 0x80620000; /* lwz r3,_PowerPCBase(r2) = get librarybase */
  4179.     }
  4180.     data[pos++] = 0x38810020; /* addi r4,r1,0x20 = {r4 := 0x20(r1)} */
  4181.     data[pos++] = 0x8003FED6; /* lwz r0,-298(r3) = load jumpin base */
  4182.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = store link register */
  4183.     data[pos++] = 0x4E800021; /* blrl = bclrl 20,0 = jump */
  4184.     data[pos++] = 0x80610034; /* lwz r3,0x34(r1) = get result D0 */
  4185.     data[pos++] = 0x382100B0; /* addi r1,r1,0xB0 = free PRCArgs structure */
  4186.     data[pos++] = 0x80010008; /* lwz r0,8(r1) = get old link register */
  4187.     data[pos++] = 0x7C0803A6; /* mtlr r0 = mtspr 8,r0 = restore link register */
  4188.     data[pos++] = 0x4E800020; /* blr = bclr 20,0 = jump back */
  4189.   }
  4190.  
  4191.   data[1] = pos-2;
  4192.   data[pos++] = HUNK_EXT;
  4193.   DoOutputDirect(data, pos*4);
  4194.  
  4195.   if(Flags & FLAG_WOSLIBBASE)
  4196.   {
  4197.     if(ap->Flags & (AMIPRAGFLAG_PPC0|AMIPRAGFLAG_PPC2))
  4198.     {
  4199.       i = strlen(BaseName);
  4200.       data[0] = (EXT_DEXT16 << 24) + ((i + 1 + 3)>>2);
  4201.       data[1] = ('_' << 24);
  4202.       DoOutputDirect(data, 5);
  4203.       DoOutputDirect(BaseName, i++);
  4204.       DoOutputDirect("\0\0\0", ((i+3)&(~3))-i);
  4205.       data[0] = 1;
  4206.       data[1] = l*4+2;    /* l holds base reference position */
  4207.       DoOutputDirect(data, 8);
  4208.     }
  4209.     OutputXDEF("__%s", name);
  4210.   }
  4211.   else
  4212.   {
  4213.     if(BaseName)
  4214.     {
  4215.       i = strlen(BaseName);
  4216.       data[0] = (EXT_DEXT16 << 24) + ((i + 1 + 3)>>2);
  4217.       data[1] = ('_' << 24);
  4218.       DoOutputDirect(data, 5);
  4219.       DoOutputDirect(BaseName, i++);
  4220.       DoOutputDirect("\0\0\0", ((i+3)&(~3))-i);
  4221.       data[0] = 1;
  4222.       data[1] = l*4+2;    /* l holds base reference position */
  4223.       DoOutputDirect(data, 8);
  4224.     } 
  4225.     if(!(ap->Flags & AMIPRAGFLAG_PPC))
  4226.     {
  4227.       data[0] = (EXT_DEXT16 << 24) + (12>>2);
  4228.       DoOutputDirect(data, 4);
  4229.       DoOutputDirect("_PowerPCBase", 12);
  4230.       data[0] = 1;
  4231.       data[1] = j*4+2; /* j holds PPC base reference position */
  4232.       DoOutputDirect(data, 8);
  4233.     }
  4234.     OutputXDEF("_%s", name);
  4235.   }
  4236.   data[0] = 0;
  4237.   DoOutputDirect(data, 4);
  4238.   if(!(Flags & FLAG_NOSYMBOL))
  4239.   {
  4240.     data[0] = HUNK_SYMBOL;
  4241.     DoOutputDirect(data, 4);
  4242.     if(Flags & FLAG_WOSLIBBASE)
  4243.       OutputSYMBOL("__%s", name);
  4244.     else
  4245.       OutputSYMBOL("_%s", name);
  4246.     data[0] = 0;
  4247.     DoOutputDirect(data, 4);
  4248.   }
  4249.   data[0] = HUNK_END;
  4250.  
  4251.   return DoOutputDirect(data, 4);
  4252. }
  4253.  
  4254. ULONG FuncVBCCPUPText(struct AmiPragma *ap, ULONG flags, STRPTR name)
  4255. {
  4256.   ULONG i;
  4257.  
  4258.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
  4259.     return 1;
  4260.  
  4261.   Flags |= FLAG_DONE;
  4262.  
  4263.   if(Flags & FLAG_ASMSECTION)
  4264.     DoOutput("\t.section %s,\"cr\"\n", name);
  4265.   DoOutput("\t.text\n");
  4266.   if(BaseName)
  4267.     DoOutput("\t.global %s\n", BaseName);
  4268.   DoOutput("\t.global PPCCallOS\n\t.global %s\n"
  4269.   "\t.align\t3\n%s:\n",name, name);
  4270.  
  4271.   if(flags & FUNCFLAG_TAG)
  4272.   {
  4273.     /* Hack the stack-frame for varargs.
  4274.        Build stack-frame, but save LR in our own stack-frame,
  4275.        because we have to overwrite the lower 8 bytes of the
  4276.        caller's frame. */
  4277.     DoOutput("\tstwu\tr1,-128(r1)\n\tmflr\tr11\n\tstw\tr11,100(r1)\n");
  4278.  
  4279.     /* Save the caller's saved SP in our own stack-frame. */
  4280.     DoOutput("\tlwz\tr11,128(r1)\n\tstw\tr11,96(r1)\n");
  4281.  
  4282.     /* Store r3-r8 at the top of our stack-frame and r9-r10
  4283.        at the low 8 bytes of the caller's frame. This way all
  4284.        arguments will reside in one continuous area. */
  4285.     for(i=3+ap->NumArgs-1; i <= 10; ++i)
  4286.       DoOutput("\tstw\tr%ld,%ld(r1)\n", i, 104+4*(i-3));
  4287.   }
  4288.   else
  4289.     DoOutput("\tstwu\tr1,-96(r1)\n\tmflr\tr11\n\tstw\tr11,100(r1)\n");
  4290.  
  4291.   for(i = 0; i < ap->NumArgs; ++i)
  4292.   {
  4293.     if(!(flags & FUNCFLAG_TAG) || i < ap->NumArgs-1)
  4294.     {
  4295.       if(i <= 7)
  4296.         DoOutput("\tstw\tr%ld,",i+3);
  4297.       else
  4298.         DoOutput("\tlwz\tr11,%ld(r1)\n\tstw\tr11,",100+(i+1-8)*4);
  4299.     }
  4300.     else
  4301.       DoOutput("\taddi\tr11,r1,%ld\n\tstw\tr11,",100+ap->NumArgs*4);
  4302.     DoOutput("%ld(r1)\n",36+4*ap->Args[i].ArgReg);
  4303.   }
  4304.  
  4305.   /* Now place the real function call */
  4306.   DoOutput("\tli\tr11,-%ld\n\tstw\tr11,8(r1)\n" /* store offset in Chaos->caos_Un.Offset */
  4307.   "\tli\tr11,1\n\tstw\tr11,12(r1)\n\tstw\tr11,24(r1)\n", ap->Bias);
  4308.   /* set M68kCacheMode and PPCCacheMode to IF_CACHEFLUSHALL */
  4309.  
  4310.   if(BaseName)
  4311.   {
  4312.     if(Flags & FLAG_SMALLDATA)
  4313.       DoOutput("\tlwz\tr11,%s@sdarx(r13)\n",BaseName);
  4314.     else
  4315.       DoOutput("\tlis\tr11,%s@ha\n\tlwz\tr11,%s@l(r11)\n",
  4316.       BaseName,BaseName);
  4317.     DoOutput("\tstw\tr11,92(r1)\n"); /* store basepointer in A6 */
  4318.   }
  4319.  
  4320.   DoOutput("\taddi\tr3,r1,8\n\tbl\tPPCCallOS\n");
  4321.   if(flags & FUNCFLAG_TAG) /* Varargs. Rebuild the caller's stack-frame. */
  4322.     DoOutput("\tlwz\tr11,96(r1)\n\tstw\tr11,128(r1)\n"
  4323.     "\tlwz\tr11,100(r1)\n\tmtlr\tr11\n\taddi\tr1,r1,128\n");
  4324.   else
  4325.     DoOutput("\tlwz\tr11,100(r1)\n\tmtlr\tr11\n\taddi\tr1,r1,96\n");
  4326.  
  4327.   return DoOutput("\tblr\n\n");
  4328. }
  4329.  
  4330. ULONG FuncVBCCPUPCode(struct AmiPragma *ap, ULONG flags, STRPTR name)
  4331. {
  4332.   ULONG i, j=0, k, *data, pos;
  4333.   struct Elf32_Shdr *esh;
  4334.   struct Elf32_Ehdr *eeh;
  4335.   struct Elf32_Sym *esym;
  4336.   struct Elf32_Rela *erel;
  4337.   UBYTE size[10];
  4338.   struct ArHeader arh;
  4339.  
  4340.   data = (ULONG *) tempbuf;
  4341.  
  4342.   if(CheckError(ap, AMIPRAGFLAG_ARGCOUNT|AMIPRAGFLAG_FLOATARG|AMIPRAGFLAG_PPC))
  4343.     return 1;
  4344.  
  4345.   Flags |= FLAG_DONE;
  4346.  
  4347.   memset((STRPTR)tempbuf,0,TEMPSIZE);    /* clear all entries */
  4348.   memset(&arh, ' ', sizeof(struct ArHeader));
  4349.  
  4350.   if((i = strlen(name)) > 15-3)
  4351.   {
  4352.     sprintf(arh.ar_name, "%.5s__%s.o/", name, name+i-5);
  4353.     arh.ar_name[15] = ' ';
  4354.   }
  4355.   else
  4356.   {
  4357.     sprintf(arh.ar_name, "%s.o/", name);
  4358.     arh.ar_name[i+3] = ' ';
  4359.   }
  4360.  
  4361.   CopyMem("942836400", arh.ar_time, 9); /* 17.11.1999 12:00:00 */
  4362.   arh.ar_uid[0] = arh.ar_gid[0] = arh.ar_mode[1] =
  4363.   arh.ar_mode[2] = '0';
  4364.   arh.ar_mode[0] = '6';
  4365.   arh.ar_fmag[0] = 96;
  4366.   arh.ar_fmag[1] = '\n';
  4367.  
  4368.   eeh = (struct Elf32_Ehdr *) data;
  4369.   eeh->e_ident[EI_MAG0] = 0x7F;
  4370.   eeh->e_ident[EI_MAG1] = 'E';
  4371.   eeh->e_ident[EI_MAG2] = 'L';
  4372.   eeh->e_ident[EI_MAG3] = 'F';
  4373.   eeh->e_ident[EI_CLASS] = ELFCLASS32;
  4374.   eeh->e_ident[EI_DATA] = ELFDATA2MSB;
  4375.   eeh->e_ident[EI_VERSION] = EV_CURRENT;
  4376.   eeh->e_type = ET_REL;
  4377.   eeh->e_machine = EM_POWERPC;
  4378.   eeh->e_version = EV_CURRENT;
  4379.   eeh->e_ehsize = sizeof(struct Elf32_Ehdr);
  4380.   eeh->e_shentsize = sizeof(struct Elf32_Shdr);
  4381.   eeh->e_shnum = 6;
  4382.   eeh->e_shstrndx = 3; /* fourth table is string table */
  4383.  
  4384.   pos = (sizeof(struct Elf32_Ehdr)>>2);
  4385.   if(flags & FUNCFLAG_TAG)
  4386.   {
  4387.     /* Hack the stack-frame for varargs.
  4388.        Build stack-frame, but save LR in our own stack-frame,
  4389.        because we have to overwrite the lower 8 bytes of the
  4390.        caller's frame. */
  4391.     data[pos++] = 0x9421FF80;         /* stwu r1,-128(r1) */
  4392.     data[pos++] = 0x7D6802A6;         /* mflr r11 = mfspr r11,8 = get link register */
  4393.     data[pos++] = 0x91610064;         /* stw r11,100(r1) */
  4394.  
  4395.     /* Save the caller's saved SP in our own stack-frame. */
  4396.     data[pos++] = 0x81610080;        /* lwz r11,128(r1) */
  4397.     data[pos++] = 0x91610060;        /* stw r11,96(r1) */
  4398.  
  4399.     /* Store r3-r8 at the top of our stack-frame and r9-r10
  4400.        at the low 8 bytes of the caller's frame. This way all
  4401.        arguments will reside in one continuous area. */
  4402.     for(i=3+ap->NumArgs-1; i <= 10; ++i)
  4403.       data[pos++] = 0x90010000 + (i<<21) + (104+4*(i-3)); /* stw rX,Y(r1) */
  4404.   }
  4405.   else
  4406.   {
  4407.     data[pos++] = 0x9421FFA0;         /* stwu r1,-96(r1) */
  4408.     data[pos++] = 0x7D6802A6;         /* mflr r11 = mfspr r11,8 = get link register */
  4409.     data[pos++] = 0x91610064;         /* stw r11,100(r1) */
  4410.   }
  4411.  
  4412.   for(i = 0; i < ap->NumArgs; ++i)
  4413.   {
  4414.     j = 36+4*ap->Args[i].ArgReg;
  4415.     if(!(flags & FUNCFLAG_TAG) || i < ap->NumArgs-1)
  4416.     {
  4417.       if(i <= 7)
  4418.         data[pos++] = 0x90010000 + ((i+3)<<21) + j;    /* stw rX,j(r1) */
  4419.       else
  4420.       {
  4421.         data[pos++] = 0x81610000 + (100+(i+1-8)*4);    /* lwz r11,X(r1) = get data from stack */
  4422.         data[pos++] = 0x91610000 + j;            /* stw r11,j(r1) */
  4423.       }
  4424.     }
  4425.     else
  4426.     {
  4427.       data[pos++] = 0x39610000 + (100+ap->NumArgs*4);    /* addi r11,r1,X */
  4428.       data[pos++] = 0x91610000 + j;            /* stw r11,X(r1) */
  4429.     }
  4430.   }
  4431.  
  4432.   /* Now place the real function call */
  4433.   data[pos++] = 0x39610000 - ap->Bias;     /* li r11,-(ap->Bias) = addi r11,0,-ap->Bias */
  4434.   data[pos++] = 0x91610008;        /* stw r11,8(r1) */
  4435.   data[pos++] = 0x39600001;        /* li r11,1 = addi r11,0,1 = get IF_CACHEFLUSHALL */
  4436.   data[pos++] = 0x9161000C;        /* stw r11,12(r1) = set M68kCacheMode */
  4437.   data[pos++] = 0x91610018;        /* stw r11,24(r1) = set PPCCacheMode */
  4438.  
  4439.   if(BaseName)
  4440.   {
  4441.     if(Flags & FLAG_SMALLDATA)
  4442.     {
  4443.       j = pos<<2; /* store reloc offset */
  4444.       data[pos++] = 0x816D0000;        /* lwz r11,BaseName@sdarx(r13) */
  4445.     }
  4446.     else
  4447.     {
  4448.       j = pos<<2; /* store reloc offset */
  4449.       data[pos++] = 0x3D600000;        /* lis r11,BaseName@ha = addis r11,0,BaseName@ha */
  4450.       data[pos++] = 0x816B0000;        /* lwz r11,BaseName@l(r11) */
  4451.     }
  4452.     data[pos++] = 0x9161005C;        /* stw r11,92(r1) */
  4453.   }
  4454.  
  4455.   data[pos++] = 0x38610008;        /* addi r3,r1,8 */
  4456.   k = pos<<2; /* store reloc offset */
  4457.   data[pos++] = 0x48000001;        /* bl PPCCallOS */
  4458.   if(flags & FUNCFLAG_TAG) /* Varargs. Rebuild the caller's stack-frame. */
  4459.   {
  4460.     data[pos++] = 0x81610060;        /* lwz r11,96(r1) */
  4461.     data[pos++] = 0x91610080;        /* stw r11,128(r1) */
  4462.     data[pos++] = 0x81610064;        /* lwz r11,100(r1) */
  4463.     data[pos++] = 0x7D6803A6;        /* mtlr r11 = mtspr 8,r11 = restore link register */
  4464.     data[pos++] = 0x38210080;        /* addi r1,r1,128 */
  4465.   }
  4466.   else
  4467.   {
  4468.     data[pos++] = 0x81610064;        /* lwz r11,100(r1) */
  4469.     data[pos++] = 0x7D6803A6;        /* mtlr r11 = mtspr 8,r11 = restore link register */
  4470.     data[pos++] = 0x38210060;        /* addi r1,r1,96 */
  4471.   }
  4472.  
  4473.   data[pos++] = 0x4E800020;        /* blr = bclr 20,0 */
  4474.  
  4475.   data[pos++] = 0x002E7379;        /* 0.sy */
  4476.   data[pos++] = 0x6D746162;        /* mtab */
  4477.   data[pos++] = 0x002E7374;        /* 0.st */
  4478.   data[pos++] = 0x72746162;        /* rtab */
  4479.   data[pos++] = 0x002E7368;        /* 0.sh */
  4480.   data[pos++] = 0x73747274;        /* strt */
  4481.   data[pos++] = 0x6162002E;        /* ab0. */
  4482.   data[pos++] = 0x74657874;        /* text */
  4483.   data[pos++] = 0x002E7265;        /* 0.re */
  4484.   data[pos++] = 0x6C612E74;        /* la.t */
  4485.   data[pos++] = 0x65787400;        /* ext0 */
  4486.   eeh->e_shoff = (pos<<2);
  4487.  
  4488.   esh = (struct Elf32_Shdr *) (data+pos);
  4489.   esh[1].sh_name = 27; /* .text */
  4490.   esh[1].sh_type = SHT_PROGBITS;
  4491.   esh[1].sh_flags = SHF_ALLOC|SHF_EXECINSTR;
  4492.   esh[1].sh_offset = sizeof(struct Elf32_Ehdr);
  4493.   esh[1].sh_size = ((pos-11)<<2)-sizeof(struct Elf32_Ehdr);
  4494.   esh[1].sh_addralign = 16;
  4495.   esh[2].sh_name = 33; /* .rela.text */
  4496.   esh[2].sh_type = SHT_RELA;
  4497.   esh[2].sh_link = 4; /* the fifth entry is symbol table */
  4498.   esh[2].sh_info = 1; /* the second entry is programm data */
  4499.   esh[2].sh_addralign = 4;
  4500.   esh[2].sh_entsize = sizeof(struct Elf32_Rela);
  4501.   esh[3].sh_name = 17; /* .shstrtab */
  4502.   esh[3].sh_type = SHT_STRTAB;
  4503.   esh[3].sh_offset = (pos<<2)-44;
  4504.   esh[3].sh_size = 44;
  4505.   esh[3].sh_addralign = 1;
  4506.   esh[4].sh_name = 1; /* .symtab */
  4507.   esh[4].sh_type = SHT_SYMTAB;
  4508.   esh[4].sh_link = 5; /* the second entry is our string table */
  4509.   esh[4].sh_info = 2;
  4510.   esh[4].sh_addralign = 4;
  4511.   esh[4].sh_entsize = sizeof(struct Elf32_Sym);
  4512.   esh[5].sh_name = 9; /* .strtab */
  4513.   esh[5].sh_type = SHT_STRTAB;
  4514.   esh[5].sh_addralign = 1;
  4515.   pos += (sizeof(struct Elf32_Shdr)>>2)*6;    /* skip the section headers */
  4516.  
  4517.   esh[4].sh_offset = (pos << 2);
  4518.   esym = (struct Elf32_Sym *) (data+pos);
  4519.   esym[1].st_info = ELF32_ST_INFO(STB_LOCAL,STT_SECTION);
  4520.   esym[1].st_shndx = 1; /* the second entry is program section! */
  4521.   pos += BaseName ? 5*((sizeof(struct Elf32_Sym))>>2) : 4*((sizeof(struct Elf32_Sym))>>2);
  4522.   esh[4].sh_size = (pos<<2)-esh[4].sh_offset;
  4523.  
  4524.   esh[5].sh_offset = (pos<<2);
  4525.   esym[2].st_name = 1;
  4526.   esym[2].st_info = ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE);
  4527.   esym[2].st_shndx = 1; /* the second entry is program section! */
  4528.   sprintf(((STRPTR)(data+pos))+1, name); i = 1 + strlen(name) +1;
  4529.   esym[3].st_name = i;
  4530.   esym[3].st_info = ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE);
  4531.   sprintf(((STRPTR)(data+pos))+i, "PPCCallOS"); i += 10;
  4532.   if(BaseName)
  4533.   {
  4534.     esym[4].st_name = i;
  4535.     esym[4].st_info = ELF32_ST_INFO(STB_GLOBAL,STT_NOTYPE);
  4536.     sprintf(((STRPTR)(data+pos))+i, BaseName); i += strlen(BaseName)+1;
  4537.   }
  4538.   pos += (i+3)>>2; /* long aligned! */
  4539.   esh[5].sh_size = i;
  4540.  
  4541.   erel = (struct Elf32_Rela *) (data+pos);
  4542.   esh[2].sh_offset = (pos << 2);
  4543.   j -= (sizeof(struct Elf32_Ehdr)-2);
  4544.   k -= sizeof(struct Elf32_Ehdr);
  4545.   if(!BaseName)
  4546.   {
  4547.     erel[0].r_offset = k;
  4548.     erel[0].r_info = ELF32_R_INFO(3,R_PPC_REL24); /* entry 3, type 10 */
  4549.     pos += (sizeof(struct Elf32_Rela)>>2);
  4550.   }
  4551.   else if(Flags & FLAG_SMALLDATA)
  4552.   {
  4553.     erel[0].r_offset = k;
  4554.     erel[0].r_info = ELF32_R_INFO(3,R_PPC_REL24); /* entry 3, type 10 */
  4555.     erel[1].r_offset = j;
  4556.     erel[1].r_info = ELF32_R_INFO(4,R_PPC_SDAREL16); /* entry 3, type 32 */
  4557.     pos += (2*sizeof(struct Elf32_Rela)>>2);
  4558.   }
  4559.   else
  4560.   {
  4561.     erel[0].r_offset = k;
  4562.     erel[0].r_info = ELF32_R_INFO(3,R_PPC_REL24); /* entry 3, type 10 */
  4563.     erel[1].r_offset = j;
  4564.     erel[1].r_info = ELF32_R_INFO(4,R_PPC_ADDR16_HA); /* entry 4, type 6 */
  4565.     erel[2].r_offset = j+4;
  4566.     erel[2].r_info = ELF32_R_INFO(4,R_PPC_ADDR16_LO); /* entry 4, type 4 */
  4567.     pos += (3*sizeof(struct Elf32_Rela)>>2);
  4568.   }
  4569.   esh[2].sh_size = (pos<<2)-esh[2].sh_offset;
  4570.  
  4571.   j = pos<<2;
  4572.   for(i = 9; j; --i) /* make decimal number */
  4573.   {
  4574.     size[i] = (j%10)+'0';
  4575.     j /= 10;
  4576.   }
  4577.   for(j = 0; i < 9; ++j)
  4578.     arh.ar_size[j] = size[++i]; 
  4579.   
  4580.   DoOutputDirect(&arh, sizeof(struct ArHeader));
  4581.   return DoOutputDirect(data, pos*4);
  4582. }
  4583.  
  4584. ULONG CallFunc(ULONG tagmode, STRPTR comment, FuncType Func)
  4585. {
  4586.   struct Comment *com = 0;
  4587.   struct AmiPragma *ap;
  4588.  
  4589.   if(comment)
  4590.     com = (struct Comment *) Comment.First;
  4591.  
  4592.   for(ap = (struct AmiPragma *) AmiPragma.First; ap && !CTRL_C;
  4593.   ap = (struct AmiPragma *) ap->List.Next)
  4594.   {
  4595.     if(BaseName && (ap->Flags & AMIPRAGFLAG_A6USE))
  4596.     {
  4597.       DoError(ERR_A6_NOT_ALLOWED, ap->Line);
  4598.     }
  4599.     else if((ap->Flags & AMIPRAGFLAG_PUBLIC) || (Flags & FLAG_PRIVATE))
  4600.     {
  4601.       while(com && com->Bias <= ap->Bias)
  4602.       {
  4603.         if(!DoOutput(comment, com->Data))
  4604.           return 0;
  4605.         com = (struct Comment *) com->List.Next;
  4606.       }
  4607.  
  4608. #ifdef DEBUG_OLD
  4609.   Printf("Processing %s\n", ap->FuncName);
  4610. #endif
  4611.  
  4612.       if(tagmode != TAGMODE_TAGS && ap->FuncName &&
  4613.       !Func(ap, FUNCFLAG_NORMAL, ap->FuncName))
  4614.         return 0;
  4615.  
  4616.       if(tagmode && ap->TagName && !Func(ap, FUNCFLAG_TAG, ap->TagName))
  4617.         return 0;
  4618.  
  4619.       if(ap->AliasName &&
  4620.       (((ap->AliasName->Type & FUNCFLAG_TAG) && tagmode) ||
  4621.       (!(ap->AliasName->Type & FUNCFLAG_TAG) && tagmode != TAGMODE_TAGS)) &&
  4622.       !Func(ap, FUNCFLAG_ALIAS|ap->AliasName->Type, ap->AliasName->AliasName))
  4623.         return 0;
  4624.     }
  4625.   }
  4626.   while(com)
  4627.   {
  4628.     if(!DoOutput(comment, com->Data))
  4629.       return 0;
  4630.     com = (struct Comment *) com->List.Next;
  4631.   }
  4632.   return 1;
  4633. }
  4634.  
  4635. /* ------------------------------------------------------------------ */
  4636.  
  4637. LONG AddClibEntry(STRPTR buffer, STRPTR bufend, ULONG linenum)
  4638. {
  4639.   STRPTR buf = buffer;
  4640.   struct ClibData d, *f;
  4641.  
  4642.   memset(&d, 0, sizeof(struct ClibData));
  4643.   if(!GetCPPType(&d.ReturnType, SkipBlanks(buf)))
  4644.   {
  4645.     DoError(ERR_UNKNOWN_VARIABLE_TYPE, linenum, 0);
  4646.     return 0;
  4647.   }
  4648.   d.FuncName = SkipBlanks(d.ReturnType.TypeStart+d.ReturnType.FullLength);
  4649.   while(*(buf++) != '('/*)*/)
  4650.     ;
  4651.   *(SkipName(d.FuncName)) = 0;
  4652.   buf = SkipBlanksRet(buf);
  4653.  
  4654.   while(*buf != /*(*/')' && buf < bufend)
  4655.   {
  4656.     if(d.NumArgs == MAXREGPPC+1)
  4657.     {
  4658.       DoError(ERR_TO_MUCH_ARGUMENTS, linenum);
  4659.       return 0;
  4660.     }
  4661.     else if(!GetCPPType(&d.Args[d.NumArgs++], buf))
  4662.     {
  4663.       DoError(ERR_UNKNOWN_VARIABLE_TYPE, linenum, d.NumArgs);
  4664.       return 0;
  4665.     }
  4666.  
  4667.     buf += d.Args[d.NumArgs-1].FullLength;
  4668.     while(*buf != ',' && *buf != /*(*/')' && buf < bufend)
  4669.       ++buf;
  4670. #ifdef DEBUG_OLD
  4671.   Printf("Added argument %ld for %s (%ld bytes)\n", d.NumArgs, d.FuncName,
  4672.   d.Args[d.NumArgs-1].FullLength);
  4673. #endif
  4674.     if(*buf == ',')
  4675.       buf = SkipBlanksRet(++buf);
  4676.   }
  4677.  
  4678.   if(d.NumArgs == 1 && IsCPPType(&d.Args[0], CPP_TYPE_VOID))
  4679.     d.NumArgs = 0; /* void arguments are no arguments */
  4680.  
  4681.   if(!(f = (struct ClibData *) AllocListMem(sizeof(struct ClibData))))
  4682.     return -1;
  4683.  
  4684.   CopyMem(&d, f, sizeof(struct ClibData));
  4685.  
  4686.   if(!clibdata)
  4687.     clibdata = f;
  4688.   else
  4689.   {
  4690.     struct ClibData *e = clibdata;
  4691.     while(e->Next)
  4692.       e = e->Next;
  4693.     e->Next = f;
  4694.   }
  4695.  
  4696. #ifdef DEBUG_OLD
  4697.   Printf("Added prototype for %s (line %ld, %ld bytes) with %ld args\n",
  4698.   f->FuncName, linenum, buf-buffer, f->NumArgs);
  4699. #endif
  4700.   return buf-buffer;
  4701. }
  4702.  
  4703. LONG ScanClibFile(STRPTR buf, STRPTR bufend)
  4704. {
  4705.   STRPTR linestart = buf;
  4706.   ULONG linenum = 1;
  4707.  
  4708.   while(buf < bufend && !CTRL_C)
  4709.   {
  4710.     if(*buf == '/' && buf[1] == '*')
  4711.     {
  4712.       while(buf < bufend && (*buf != '*' || buf[1] != '/'))
  4713.       {
  4714.         if(*(buf++) == '\n')
  4715.         {
  4716.           ++linenum; linestart = buf;
  4717.         } /* skip comments */
  4718.       }
  4719.     }
  4720.     else if(*buf == '/' && buf[1] == '/')
  4721.     {
  4722.       while(buf < bufend && *buf != '\n')
  4723.         ++buf; /* skip line comments */
  4724.     }
  4725.     else if(*buf == '\n')
  4726.     {
  4727.       linestart = ++buf; ++linenum;
  4728.     }
  4729.     else if(*buf == '('/*)*/)
  4730.     {
  4731.       LONG i;
  4732.  
  4733.       if((i = AddClibEntry(linestart, bufend, linenum)) == -1) /* no memory */
  4734.         return 0;
  4735.       else if(!i)
  4736.       {
  4737.         while(buf < bufend && *buf != '\n')
  4738.           ++buf; /* skip this line */
  4739.       }
  4740.       else
  4741.       {
  4742.         i -= buf-linestart;
  4743.         while(buf < bufend && i-- > 0)
  4744.         {
  4745.           if(*(buf++) == '\n')
  4746.           {
  4747.             linestart = buf;
  4748.             ++linenum;
  4749.           } /* skip this function */
  4750.         }
  4751.       }
  4752.     }
  4753.     else
  4754.       ++buf;
  4755.   } /* while */
  4756.   return 1;
  4757. }
  4758.  
  4759. LONG IsCPPType(struct CPP_NameType *data, UBYTE type)
  4760. {
  4761.   if(!data || data->Flags || data->Type != type || data->PointerDepth)
  4762.     return 0;
  4763.   return type;
  4764. }
  4765.  
  4766. LONG GetCPPType(struct CPP_NameType *data, STRPTR start)
  4767. {
  4768.   ULONG ok = 1;
  4769.   STRPTR u;
  4770.  
  4771.   data->TypeStart = SkipBlanks(start);
  4772.  
  4773.   do
  4774.   {
  4775.     start = SkipBlanks((u = start));
  4776.     if(!strncmp("...",start,3))
  4777.     {
  4778.       data->Type = CPP_TYPE_VARARGS; return 1;
  4779.     }
  4780.     if(CheckKeyword(start, "const", 5) || CheckKeyword(start, "CONST", 5))
  4781.     {
  4782.       data->Flags |= CPP_FLAG_CONST; start += 6;
  4783.     }
  4784.     else if(CheckKeyword(start, "signed", 6))
  4785.       start += 7;
  4786.     else if(CheckKeyword(start, "unsigned", 8))
  4787.     {
  4788.       data->Flags |= CPP_FLAG_UNSIGNED; start += 9;
  4789.     }
  4790.     else if(CheckKeyword(start, "struct", 6))
  4791.     {
  4792.       start = SkipBlanks(start+6);
  4793.       data->Flags |= CPP_FLAG_STRUCT;
  4794.       if(*start != '?') /* ? for external types */
  4795.       {
  4796.         start = SkipName((data->StructureName = start));
  4797.         data->StructureLength = start-data->StructureName;
  4798.       }
  4799.       else
  4800.       {
  4801.         data->StructureLength = 0;
  4802.         data->StructureName = "";
  4803.         ++start;
  4804.       }
  4805.     }
  4806.     else if(CheckKeyword(start, "union", 5))
  4807.     {
  4808.       start = SkipBlanks(start+5);
  4809.       data->Flags |= CPP_FLAG_UNION;
  4810.       if(*start != '?') /* ? for external types */
  4811.       {
  4812.         start = SkipName((data->StructureName = start));
  4813.         data->StructureLength = start-data->StructureName;
  4814.       }
  4815.       else
  4816.       {
  4817.         data->StructureLength = 0;
  4818.         data->StructureName = "";
  4819.         ++start;
  4820.       }
  4821.     }
  4822.     else if(CheckKeyword(start, "enum", 4))
  4823.     {
  4824.       start = SkipBlanks(start+4);
  4825.       data->Flags |= CPP_FLAG_ENUM;
  4826.       if(*start != '?') /* ? for external types */
  4827.       {
  4828.         start = SkipName((data->StructureName = start));
  4829.         data->StructureLength = start-data->StructureName;
  4830.       }
  4831.       else
  4832.       {
  4833.         data->StructureLength = 0;
  4834.         data->StructureName = "";
  4835.         ++start;
  4836.       }
  4837.     }
  4838.     else if(*start == '*')
  4839.     {
  4840.       ++start; ++data->PointerDepth;
  4841.     }
  4842.     else
  4843.     {
  4844.       ULONG i;
  4845.  
  4846.       for(i = 0; CPP_Field[i].Text; ++i)
  4847.       {
  4848.         if(!strncmp(start, CPP_Field[i].Text, CPP_Field[i].Length) &&
  4849.         (start[CPP_Field[i].Length] == ' ' ||
  4850.         start[CPP_Field[i].Length] == '\t' ||
  4851.         start[CPP_Field[i].Length] == '\n' ||
  4852.         start[CPP_Field[i].Length] == ',' ||
  4853.         start[CPP_Field[i].Length] == /*(*/')' ||
  4854.         start[CPP_Field[i].Length] == '('/*)*/ ||
  4855.         start[CPP_Field[i].Length] == '*'))
  4856.         {
  4857.           start += CPP_Field[i].Length;
  4858.           data->Type = CPP_Field[i].Type;
  4859.           data->Flags |= CPP_Field[i].Flags;
  4860.           if(CPP_Field[i].Flags & CPP_FLAG_POINTER)
  4861.             ++data->PointerDepth;
  4862.           break;
  4863.         }
  4864.       }
  4865.       if(CPP_Field[i].Text)
  4866.         continue;
  4867.       else if(extnames)
  4868.       {
  4869.         struct CPP_ExternNames *a = extnames;
  4870.        
  4871.         while(a)
  4872.         {
  4873.           i = strlen(a->Type);
  4874.           if(!strncmp(a->Type, start, i) && !isalnum(start[i]) && 
  4875.           start[i] != '_')
  4876.           {
  4877.             start += i;
  4878.             data->StructureName = a->NameType.StructureName;
  4879.             data->FuncArgs = a->NameType.FuncArgs;
  4880.             data->StructureLength = a->NameType.StructureLength;
  4881.             data->PointerDepth += a->NameType.PointerDepth;
  4882.             data->Type = a->NameType.Type;
  4883.             data->Flags |= a->NameType.Flags;
  4884.             break;
  4885.           }
  4886.      
  4887.           /* check types here */
  4888.           a = a->Next;
  4889.         }
  4890.         if(a)
  4891.           continue;
  4892.       }
  4893.       break;
  4894.     }
  4895.   } while(1);
  4896.  
  4897.   if(start != SkipBlanks(u)) /* we broke the loop after increasing start */
  4898.     u = start;
  4899.  
  4900.   data->TypeLength = u - (data->TypeStart);
  4901.   data->FullLength = data->TypeLength;
  4902.  
  4903.   u = SkipBlanks(u);
  4904.  
  4905.   if(*u == '('/*)*/)
  4906.   {
  4907.     ok = 0;
  4908.     u = SkipBlanks(++u);
  4909.     if(*u == '*')
  4910.     {
  4911.       u = SkipBlanks(++u);
  4912.       if(CheckKeyword(u, "const", 5) || CheckKeyword(u, "CONST", 5))
  4913.       {
  4914.         data->Flags |= CPP_FLAG_CONST; u += 6;
  4915.       }
  4916.       u = SkipBlanks(SkipName(SkipBlanks(u)));
  4917.       if(*u == /*(*/')')
  4918.       {
  4919.         u = SkipBlanks(++u);
  4920.         if(*u == '('/*)*/)
  4921.         {
  4922.           data->Flags |= CPP_FLAG_FUNCTION;
  4923.           data->FuncArgs = u;
  4924.           ok = 1;
  4925.           u = SkipBlanks(++u);
  4926.           if(*u == /*(*/')')
  4927.             data->FuncArgs = 0;
  4928.           else
  4929.           {
  4930.             ULONG d = 0;
  4931.             while(d || *u != /*(*/')')
  4932.             {
  4933.               if(*u == '('/*)*/)
  4934.                 ++d;
  4935.               else if(*u == /*(*/')')
  4936.                 --d;
  4937.               ++u;
  4938.             }
  4939.             data->ArgsLength = u+1 - (data->FuncArgs);
  4940.           }
  4941.           data->FullLength = u+1 - (data->TypeStart);
  4942.         }
  4943.       }
  4944.     }
  4945.   }
  4946.  
  4947.   if(data->PointerDepth)
  4948.     data->Flags |= CPP_FLAG_POINTER;
  4949.  
  4950.   if((!data->Type && !data->Flags) || !ok)
  4951.     return 0;
  4952.   return 1;
  4953. }
  4954.  
  4955. struct ClibData *GetClibFunc(STRPTR name, struct AmiPragma *ap, ULONG flags)
  4956. {
  4957.   struct ClibData *d = clibdata;
  4958.  
  4959.   while(d && strcmp(name, d->FuncName))
  4960.     d = d->Next;
  4961.  
  4962.   if(!d)
  4963.   {
  4964.     if(!(ap->Flags & AMIPRAGFLAG_NOCLIB))
  4965.     {
  4966.       DoError(ERR_PROTOTYPE_MISSING, 0, name);
  4967.       ap->Flags |= AMIPRAGFLAG_NOCLIB;
  4968.     }
  4969.   }
  4970.   else if(ap->CallArgs != d->NumArgs && (!(flags & FUNCFLAG_TAG) ||
  4971.   ap->CallArgs+1 != d->NumArgs))
  4972.   {
  4973.     if(!(ap->Flags & (AMIPRAGFLAG_CLIBARGCNT|AMIPRAGFLAG_DIDARGWARN)))
  4974.     {
  4975.       DoError(ERR_CLIB_ARG_COUNT, 0, name, d->NumArgs, ap->NumArgs);
  4976.       ap->Flags |= AMIPRAGFLAG_CLIBARGCNT;
  4977.     }
  4978.     return 0;
  4979.   }
  4980.  
  4981.   return d;  
  4982. }
  4983.  
  4984. LONG CheckKeyword(STRPTR string, STRPTR keyword, LONG size)
  4985. {
  4986.   if(!strncmp(string, keyword, size))
  4987.   {
  4988.     string += size;
  4989.     if(*string == ' ' || *string == '\t' || *string == '\n')
  4990.       return size;
  4991.   }
  4992.   return 0;
  4993. }
  4994.  
  4995. /* return non zero, when ok, return 0xFFFFFFFF when STRPTR and not flags */
  4996. ULONG CopyCPPType(STRPTR buffer, ULONG flag, struct ClibData *cd,
  4997. struct AmiArgs *args)
  4998. {
  4999. /* when flag, then STRPTR is unsigned char * mode, else signed char * */
  5000.   ULONG ret = 1;
  5001.   ULONG i, j, k = 0;
  5002.  
  5003.   for(i = 0; i < cd->NumArgs; ++i)
  5004.   {
  5005.     struct CPP_NameType *nt;
  5006.  
  5007.     nt = &cd->Args[i];
  5008.  
  5009.     if(!flag && (nt->Flags & CPP_FLAG_STRPTR))
  5010.       ret = 0xFFFFFFFF;
  5011.  
  5012.     if(args && (Flags & FLAG_LOCALREG) && (nt->Type != CPP_TYPE_VARARGS))
  5013.     {
  5014.       *(buffer++) = CPP_TYPE_REGISTER;
  5015.       *(buffer++) = args[k].ArgReg + (args[k].ArgReg < 10 ? '0' : 'A'-10);
  5016.     }
  5017.     if(nt->Flags & CPP_FLAG_FUNCTION)
  5018.     {
  5019.       *(buffer++) = CPP_TYPE_POINTER; *(buffer++) = CPP_TYPE_FUNCTION;
  5020.     }
  5021.     for(j = 0; j < nt->PointerDepth; ++j)
  5022.       *(buffer++) = CPP_TYPE_POINTER;
  5023.     if(nt->Flags & CPP_FLAG_CONST)
  5024.       *(buffer++) = CPP_TYPE_CONST;
  5025.     if((nt->Flags & CPP_FLAG_UNSIGNED) &&
  5026.     !(flag && (nt->Flags & CPP_FLAG_STRPTR)))
  5027.       *(buffer++) = CPP_TYPE_UNSIGNED;
  5028.     if(nt->Flags & CPP_FLAG_ENUM)
  5029.       *(buffer++) = CPP_TYPE_ENUM;
  5030.     if(nt->Type)
  5031.       *(buffer++) = cd->Args[i].Type;
  5032.     else
  5033.     {
  5034.       ULONG i;
  5035.       sprintf(buffer, "%02ld", (ULONG) nt->StructureLength); buffer += 2;
  5036.       for(i = 0; i < nt->StructureLength; ++i)
  5037.         *(buffer++) = nt->StructureName[i];
  5038.     }
  5039.     if(nt->Flags & CPP_FLAG_FUNCTION)
  5040.     {
  5041. //      if(nt.FuncArgs)
  5042. //      {
  5043. //        ******** do something here
  5044. //        while(*buffer)
  5045. //          ++buffer;
  5046. //      }
  5047.       *(buffer++) = CPP_TYPE_FUNCEND;
  5048.     }
  5049.     ++k;
  5050.     if(IsCPPType(nt, CPP_TYPE_DOUBLE))  /* double needs 2 registers */
  5051.       ++k;
  5052.   }
  5053.  
  5054.   *(buffer) = 0;
  5055.  
  5056.   return ret;
  5057. }
  5058.  
  5059. ULONG OutClibType(struct CPP_NameType *nt, STRPTR txt)
  5060. {
  5061.   DoOutputDirect(nt->TypeStart, nt->TypeLength);
  5062.   if(!DoOutput((nt->Flags & CPP_FLAG_FUNCTION) ? (txt ? " (*%s)" : " (*)") :
  5063.   (txt ? " %s" : ""), txt))
  5064.     return 0;
  5065.  
  5066.   if(nt->Flags & CPP_FLAG_FUNCTION)
  5067.   {
  5068.     if(nt->FuncArgs)
  5069.       DoOutputDirect(nt->FuncArgs, nt->ArgsLength);
  5070.     else
  5071.       return DoOutput("()");
  5072.   }
  5073.  
  5074.   return 1;
  5075. }
  5076.  
  5077. ULONG OutPASCALType(struct CPP_NameType *t, STRPTR txt, ULONG ret)
  5078. {
  5079.   LONG i = t->PointerDepth;
  5080.  
  5081.   if(t->Flags & CPP_FLAG_CONST)
  5082.     DoOutput("CONST ");
  5083.   if(!ret && i == 1 &&
  5084.   (t->Type == CPP_TYPE_LONG || t->Type == CPP_TYPE_WORD))
  5085.   {
  5086.     DoOutput("VAR "); --i;
  5087.   }
  5088.  
  5089.   DoOutput("%s : ", txt);
  5090.  
  5091.   if(!i && t->Flags == CPP_FLAG_BOOLEAN)
  5092.     return DoOutput("BOOLEAN");
  5093.   else if(i && t->Type == CPP_TYPE_VOID)
  5094.     return DoOutput("POINTER");
  5095.   else if(t->Flags & CPP_FLAG_FUNCTION)
  5096.     return DoOutput("tPROCEDURE");
  5097.  
  5098.   while(i--)
  5099.     DoOutput("p");
  5100.  
  5101.   if((t->Flags & (CPP_FLAG_STRUCT|CPP_FLAG_UNION)) && t->StructureLength)
  5102.   {
  5103.     if(!t->PointerDepth)
  5104.       DoOutput("t");
  5105.     return DoOutputDirect(t->StructureName, t->StructureLength);
  5106.   }
  5107.  
  5108.   if(t->Flags & CPP_FLAG_UNSIGNED)
  5109.   {
  5110.     if(t->Type == CPP_TYPE_LONG)
  5111.       return DoOutput("CARDINAL");
  5112.     if(t->Type == CPP_TYPE_WORD)
  5113.       return DoOutput("WORD");
  5114.     if(t->Type == CPP_TYPE_BYTE)
  5115.       return DoOutput(t->PointerDepth == 1 ? "CHAR" : "BYTE");
  5116.   }
  5117.   else if(t->Type == CPP_TYPE_WORD)
  5118.     return DoOutput("INTEGER");
  5119.   else if(t->Type == CPP_TYPE_BYTE)
  5120.     return DoOutput("SHORTINT");
  5121.   return DoOutput("LONGINT");
  5122. }
  5123.  
  5124. /* ------------------------------------------------------------------ */
  5125.  
  5126. ULONG CallPrag(ULONG tagmode, STRPTR type, FuncType Func)
  5127. {
  5128.   if(type)
  5129.     if((*type && !DoOutput("#if%s\n", type)) ||
  5130.     !(CallFunc(tagmode, tagmode ? 0 : "/%s */\n", Func)) ||
  5131.     (*type && !DoOutput("#endif\n")) || CTRL_C)
  5132.       return 0;
  5133.   return 1;
  5134. }
  5135.  
  5136. ULONG CreatePragmaFile(STRPTR amicall, STRPTR libcall, STRPTR amitags,
  5137. STRPTR libtags, ULONG mode)
  5138. {
  5139.   switch(mode)
  5140.   {
  5141.   case PRAGMODE_PRAGLIB: DoOutput("#ifndef _INCLUDE_PRAGMA_%s_LIB_H\n"
  5142.     "#define _INCLUDE_PRAGMA_%s_LIB_H\n", ShortBaseNameUpper,
  5143.     ShortBaseNameUpper); break;
  5144.   case PRAGMODE_PRAGSLIB: DoOutput("#ifndef PRAGMAS_%s_LIB_H\n#define "
  5145.     "PRAGMAS_%s_LIB_H\n", ShortBaseNameUpper, ShortBaseNameUpper); break;
  5146.   case PRAGMODE_PRAGSPRAGS: DoOutput("#ifndef PRAGMAS_%s_PRAGMAS_H\n#define "
  5147.     "PRAGMAS_%s_PRAGMAS_H\n", ShortBaseNameUpper, ShortBaseNameUpper); break;
  5148.   case PRAGMODE_NONE: break;
  5149.   default: return 0;
  5150.   }
  5151.  
  5152.   if(HEADER)
  5153.   {
  5154.     DoOutput("\n");
  5155.     DoOutputDirect(HEADER, headersize);
  5156.   }
  5157.  
  5158.   if(mode != PRAGMODE_NONE && !DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
  5159.   "<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
  5160.     return 0;
  5161.  
  5162.   if((Flags & FLAG_EXTERNC) &&
  5163.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  5164.     return 0;
  5165.  
  5166.   if(Flags & FLAG_GNUPRAG)
  5167.   {
  5168.     DoOutput("#ifdef " TEXT_GNUC "\n#include <inline/%s.h>\n#endif\n",
  5169.     ShortBaseName);
  5170.     Flags |= FLAG_DONE;
  5171.   }
  5172.  
  5173.   if(
  5174.   !CallPrag(TAGMODE_NORMAL, amicall, FuncAMICALL) ||
  5175.   !CallPrag(TAGMODE_NORMAL, libcall, FuncLIBCALL))
  5176.     return 0;
  5177.  
  5178.   if(tagfuncs)
  5179.   {
  5180.     if(
  5181.     !CallPrag(TAGMODE_TAGS, amitags, FuncAMICALL) ||
  5182.     !CallPrag(TAGMODE_TAGS, libtags, FuncLIBCALL))
  5183.       return 0;
  5184.   }
  5185.  
  5186.   if((Flags & FLAG_EXTERNC) &&
  5187.   !DoOutput("\n#ifdef __cplusplus\n}\n#endif\n"))
  5188.     return 0;
  5189.  
  5190.   switch(mode)
  5191.   {
  5192.   case PRAGMODE_PRAGLIB: DoOutput("\n#endif\t/*  _INCLUDE_PRAGMA_%s_LIB_H  */\n",
  5193.     ShortBaseNameUpper); break;
  5194.   case PRAGMODE_PRAGSLIB: DoOutput("\n#endif\t/*  PRAGMAS_%s_LIB_H  */\n",
  5195.     ShortBaseNameUpper); break;
  5196.   case PRAGMODE_PRAGSPRAGS: DoOutput("\n#endif\t/*  PRAGMAS_%s_PRAGMA_H  */\n",
  5197.     ShortBaseNameUpper); break;
  5198.   case PRAGMODE_NONE: break;
  5199.   default: return 0;
  5200.   }
  5201.   return Output_Error;
  5202. }
  5203.  
  5204. ULONG CreateCSTUBSFile(void)
  5205. {
  5206.   DoOutput("#ifndef _INCLUDE_%s_CSTUBS_H\n#define _INCLUDE_%s_CSTUBS_H\n",
  5207.     ShortBaseNameUpper, ShortBaseNameUpper);
  5208.  
  5209.   if(!clibdata)
  5210.   {
  5211.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  5212.   }
  5213.  
  5214.   if(HEADER)
  5215.   {
  5216.     DoOutput("\n");
  5217.     DoOutputDirect(HEADER, headersize);
  5218.   }
  5219.  
  5220.   if(!DoOutput("\n#ifndef CLIB_%s_PROTOS_H\n#include "
  5221.   "<clib/%s_protos.h>\n#endif\n\n", ShortBaseNameUpper, ShortBaseName))
  5222.     return 0;
  5223.  
  5224.   if(!CallFunc(TAGMODE_TAGS, "/%s */\n", FuncCSTUBS))
  5225.     return 0;
  5226.  
  5227.   return DoOutput("#endif\t/*  _INCLUDE_%s_CSTUBS_H  */\n",
  5228.   ShortBaseNameUpper);
  5229. }
  5230.  
  5231. ULONG CreateLVOFile(ULONG mode)
  5232. {
  5233.   STRPTR data = "_LVO_I";
  5234.  
  5235.   if(mode == 2 || mode == 4)
  5236.     data = "_LIB_I";
  5237.  
  5238.   if(!DoOutput("\t\tIFND LIBRARIES_%s%s\nLIBRARIES_%s%s\tSET\t1\n\n",
  5239.   ShortBaseNameUpper, data, ShortBaseNameUpper, data) ||
  5240.   (HEADER && (!DoOutput("\n") || !DoOutputDirect(HEADER, headersize))) ||
  5241.   (mode <= 2 && !CallFunc(TAGMODE_NORMAL, 0, FuncLVOXDEF)) ||
  5242.   !CallFunc(TAGMODE_NORMAL, "\n%s", FuncLVO) ||
  5243.   !DoOutput("\n\n\t\tENDC\n") || CTRL_C)
  5244.     return 0;
  5245.  
  5246.   return 1;
  5247. }
  5248.  
  5249. ULONG CreateAsmStubs(ULONG mode, ULONG callmode)
  5250. {
  5251.   /* 1 = Text, 2 = Code */
  5252.   switch(mode)
  5253.   {
  5254.   case 1:
  5255.     if(HEADER)
  5256.     {
  5257.       DoOutput("\n");
  5258.       DoOutputDirect(HEADER, headersize);
  5259.     }
  5260.     
  5261.     if(!(Flags & FLAG_ASMSECTION))
  5262.       DoOutput("\tSECTION\t\"%s_STUBS\",CODE\n\tXREF\t_%s\n", ShortBaseNameUpper, BaseName);
  5263.     if(!CallFunc(callmode, "\n%s", FuncAsmText))
  5264.       return 0;
  5265.     break;
  5266.   case 2:
  5267.     if(!CallFunc(callmode, 0, FuncAsmCode))
  5268.       return 0;
  5269.     break;
  5270.   }
  5271.  
  5272.   if(CTRL_C)
  5273.     return 0;
  5274.   return 1;
  5275. }
  5276.  
  5277. ULONG CreateProtoFile(ULONG Type)
  5278. {
  5279.   STRPTR str1 = "pragma", str2 = "lib";
  5280.  
  5281.   DoOutput("#ifndef _PROTO_%s_H\n#define _PROTO_%s_H\n", ShortBaseNameUpper,
  5282.   ShortBaseNameUpper);
  5283.  
  5284.   if(HEADER)
  5285.   {
  5286.     DoOutput("\n");
  5287.     DoOutputDirect(HEADER, headersize);
  5288.   }
  5289.  
  5290.   switch(Type)
  5291.   {
  5292.     case 4: str1 = "pragmas"; /* no break; */
  5293.     case 2: str2 = "pragmas"; break;
  5294.     case 3: str1 = "pragmas"; break;
  5295.     case 5: str1 = "local"; str2 = "loc"; break;
  5296.   }
  5297.  
  5298.   DoOutput("\n#ifndef EXEC_TYPES_H\n#include <exec/types.h>\n#endif\n");
  5299.   if(Type != 5)
  5300.     DoOutput("#ifndef CLIB_%s_PROTOS_H\n"
  5301.     "#include <clib/%s_protos.h>\n#endif\n",
  5302.     ShortBaseNameUpper, ShortBaseName);
  5303.   if(Type != 8)
  5304.   {
  5305.     if(Type >= 6)
  5306.     {
  5307.       DoOutput("\n#ifdef " TEXT_GNUC "\n#include <inline/%s.h>\n",
  5308.       ShortBaseName);
  5309.       if(Type != 7)
  5310.         DoOutput("#else");
  5311.     }
  5312.     if(Type != 7)
  5313.       DoOutput("\n#include <%s/%s_%s.h>\n", str1, ShortBaseName, str2);
  5314.     if(Type >= 6)
  5315.       DoOutput("#endif\n");
  5316.   }
  5317.  
  5318.   if(BaseName)
  5319.   {
  5320.     DoOutput("\n#ifndef __NOLIBBASE__\nextern struct %s *", GetBaseType());
  5321.     if(Type == 7)
  5322.       DoOutput("\n#ifdef __CONSTLIBBASEDECL__\n__CONSTLIBBASEDECL__\n"
  5323.       "#endif\n");
  5324.     DoOutput("%s;\n#endif\n", BaseName);
  5325.   }
  5326.  
  5327.   Flags |= FLAG_DONE;
  5328.  
  5329.   return DoOutput("\n#endif\t/*  _PROTO_%s_H  */\n", ShortBaseNameUpper);
  5330. }
  5331.  
  5332. ULONG CreateLocalData(STRPTR to, ULONG callmode, STRPTR clibbuf,
  5333. ULONG clibsize)
  5334. {
  5335.   UBYTE a[40];
  5336.  
  5337.   DoOutput("#ifndef _INCLUDE_PROTO_%s_LOC_H\n"
  5338.   "#define _INCLUDE_PROTO_%s_LOC_H\n",
  5339.   ShortBaseNameUpper, ShortBaseNameUpper);
  5340.  
  5341.   if(HEADER)
  5342.   {
  5343.     DoOutput("\n");
  5344.     DoOutputDirect(HEADER, headersize);
  5345.   }
  5346.  
  5347.   DoOutput("\n");
  5348.  
  5349.   { /* copies the include lines */
  5350.     STRPTR str = clibbuf, strend = clibbuf + clibsize;
  5351.     ULONG i = 0;
  5352.  
  5353.     /* works too, when no clibbuf, because then following is everytime false */
  5354.     while(str < strend)
  5355.     {
  5356.       if(!strncmp(str, "#include", 8))
  5357.       {
  5358.         DoOutput("%s\n",str); ++i;
  5359.       }
  5360.       while(*(str++))
  5361.         ;
  5362.     }
  5363.     DoOutput(i ? "\n" : "#include <exec/types.h>\n\n");
  5364.   }
  5365.  
  5366.   if((Flags & FLAG_EXTERNC) &&
  5367.   !DoOutput("#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n"))
  5368.     return 0;
  5369.  
  5370.   if(!CallFunc(callmode, "/%s */\n", FuncLocText))
  5371.     return 0;
  5372.  
  5373.   if((Flags & FLAG_EXTERNC) &&
  5374.   !DoOutput("#ifdef __cplusplus\n}\n#endif\n\n"))
  5375.     return 0;
  5376.  
  5377.   DoOutput("#endif\t/*  _INCLUDE_PROTO_%s_LOC_H  */\n", ShortBaseNameUpper);
  5378.   Out(out.size); /* clears buffer */
  5379.  
  5380.   sprintf(a, "%s_loc.lib", ShortBaseName);
  5381.   if(!CloseDest(to) || !(out.file = Open(a, MODE_NEWFILE)))
  5382.     return 0;
  5383.  
  5384.   CallFunc(callmode, 0, FuncLocCode);
  5385.   
  5386.   return CloseDest(a);
  5387. }
  5388.  
  5389. ULONG CreateInline(ULONG mode, ULONG callmode)
  5390. {
  5391.   if(!clibdata)
  5392.   {
  5393.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  5394.   }
  5395.  
  5396.   DoOutput("#ifndef _%sINLINE_%s_H\n#define _%sINLINE_%s_H\n",
  5397.   Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper,
  5398.   Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper);
  5399.  
  5400.   if(HEADER)
  5401.   {
  5402.     DoOutput("\n");
  5403.     DoOutputDirect(HEADER, headersize);
  5404.   }
  5405.  
  5406.   DoOutput("\n");
  5407.  
  5408.   if(mode)
  5409.   {
  5410.     if(Flags & FLAG_POWERUP)
  5411.       DoOutput("#ifndef __PPCINLINE_STUB_H\n"
  5412.       "#include <powerup/ppcinline/stubs.h>\n#endif\n\n");
  5413.     else
  5414.       DoOutput("#ifndef __INLINE_STUB_H\n"
  5415.       "#include <inline/stubs.h>\n#endif\n\n");
  5416.     if(mode == 2)
  5417.       Flags |= FLAG_INLINESTUB;
  5418.   }
  5419.   else
  5420.   {
  5421.     if(Flags & FLAG_POWERUP)
  5422.       DoOutput("#ifndef __PPCINLINE_MACROS_H\n"
  5423.       "#include <powerup/ppcinline/macros.h>\n#endif\n\n");
  5424.     else
  5425.       DoOutput("#ifndef __INLINE_MACROS_H\n"
  5426.       "#include <inline/macros.h>\n#endif\n\n");
  5427.     Flags |= FLAG_INLINENEW;
  5428.   }
  5429.  
  5430.   if(BaseName)
  5431.   {
  5432.     if(mode)
  5433.       DoOutput("#ifndef BASE_EXT_DECL\n#define BASE_EXT_DECL\n"
  5434.       "#define BASE_EXT_DECL0 extern struct %s *%s;\n#endif\n"
  5435.       "#ifndef BASE_PAR_DECL\n#define BASE_PAR_DECL\n"
  5436.       "#define BASE_PAR_DECL0 void\n#endif\n"
  5437.       "#ifndef BASE_NAME\n#define BASE_NAME %s\n#endif\n\n"
  5438.       "BASE_EXT_DECL0\n\n", GetBaseType(), BaseName, BaseName);
  5439.     else
  5440.       DoOutput("#ifndef %s_BASE_NAME\n#define %s_BASE_NAME %s\n#endif\n\n",
  5441.       ShortBaseNameUpper, ShortBaseNameUpper, BaseName);
  5442.   }
  5443.  
  5444.   if(!CallFunc(callmode, "/%s */\n", FuncInline))
  5445.     return 0;
  5446.  
  5447.   if(mode && BaseName)
  5448.     DoOutput("#undef BASE_EXT_DECL\n#undef BASE_EXT_DECL0\n"
  5449.     "#undef BASE_PAR_DECL\n#undef BASE_PAR_DECL0\n#undef BASE_NAME\n\n");
  5450.  
  5451.   return DoOutput("#endif /*  _%sINLINE_%s_H  */\n",
  5452.   Flags & FLAG_POWERUP ? "PPC" : "", ShortBaseNameUpper);
  5453. }
  5454.  
  5455. ULONG CreateSASPowerUP(ULONG callmode)
  5456. {
  5457.   DoOutput("#ifndef _PPCPRAGMA_%s_H\n#define _PPCPRAGMA_%s_H\n",
  5458.   ShortBaseNameUpper, ShortBaseNameUpper);
  5459.  
  5460.   if(HEADER)
  5461.   {
  5462.     DoOutput("\n");
  5463.     DoOutputDirect(HEADER, headersize);
  5464.   }
  5465.  
  5466.   DoOutput("\n#ifdef __GNUC__\n"
  5467.   "#ifndef _PPCINLINE__%s_H\n"
  5468.   "#include <powerup/ppcinline/%s.h>\n"
  5469.   "#endif\n"
  5470.   "#else\n\n"
  5471.   "#ifndef POWERUP_PPCLIB_INTERFACE_H\n"
  5472.   "#include <powerup/ppclib/interface.h>\n"
  5473.   "#endif\n\n"
  5474.   "#ifndef POWERUP_GCCLIB_PROTOS_H\n"
  5475.   "#include <powerup/gcclib/powerup_protos.h>\n"
  5476.   "#endif\n\n"
  5477.   "#ifndef NO_PPCINLINE_STDARG\n"
  5478.   "#define NO_PPCINLINE_STDARG\n"
  5479.   "#endif /* SAS-C PPC inlines */\n\n",
  5480.   ShortBaseNameUpper, ShortBaseName);
  5481.  
  5482.   if(BaseName)
  5483.   {
  5484.     DoOutput("#ifndef %s_BASE_NAME\n#define %s_BASE_NAME %s\n#endif\n\n",
  5485.     ShortBaseNameUpper, ShortBaseNameUpper, BaseName);
  5486.   }
  5487.  
  5488.   if(!CallFunc(callmode, "/%s */\n", FuncPowerUP))
  5489.     return 0;
  5490.  
  5491.   return DoOutput("#endif /* SAS-C PPC pragmas */\n"
  5492.   "#endif /*  _PPCPRAGMA_%s_H  */\n", ShortBaseNameUpper);
  5493. }
  5494.  
  5495. ULONG CreateProtoPowerUP(void)
  5496. {
  5497.   DoOutput("#ifndef PPCPROTO_%s_H\n#define PPCPROTO_%s_H\n",
  5498.   ShortBaseNameUpper, ShortBaseNameUpper);
  5499.  
  5500.   if(HEADER)
  5501.   {
  5502.     DoOutput("\n");
  5503.     DoOutputDirect(HEADER, headersize);
  5504.   }
  5505.  
  5506.   DoOutput("\n#include <clib/%s_protos.h>\n\n#ifdef " TEXT_GNUC "\n"
  5507.   "#include <powerup/ppcinline/%s.h>\n#else /* SAS-C */\n"
  5508.   "#include <powerup/ppcpragmas/%s_pragmas.h>\n#endif\n",
  5509.   ShortBaseName, ShortBaseName, ShortBaseName);
  5510.  
  5511.   if(BaseName)
  5512.   {
  5513.     DoOutput("\n#ifndef __NOLIBBASE__\nextern struct %s *", GetBaseType());
  5514.     DoOutput("\n#ifdef __CONSTLIBBASEDECL__\n__CONSTLIBBASEDECL__\n"
  5515.     "#endif\n%s;\n#endif\n", BaseName);
  5516.   }
  5517.  
  5518.   Flags |= FLAG_DONE;
  5519.  
  5520.   return DoOutput("\n#endif\t/*  PPCPROTO_%s_H  */\n", ShortBaseNameUpper);
  5521. }
  5522.  
  5523. ULONG CreateFPCUnit(void)
  5524. {
  5525.   if(!clibdata)
  5526.   {
  5527.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  5528.   }
  5529.  
  5530.   DoOutput("UNIT %s;\n", ShortBaseNameUpper);
  5531.  
  5532.   if(HEADER)
  5533.   {
  5534.     DoOutput("\n");
  5535.     DoOutputDirect(HEADER, headersize);
  5536.   }
  5537.  
  5538.   DoOutput("\nINTERFACE\nUSES Exec;\n\nVAR %s : p%s;\n\n", BaseName,
  5539.   GetBaseType());
  5540.  
  5541.   if(!CallFunc(TAGMODE_NORMAL, 0, FuncFPCType))
  5542.     return 0;
  5543.  
  5544.   DoOutput("\nIMPLEMENTATION\n\n");
  5545.  
  5546.   if(!CallFunc(TAGMODE_NORMAL, "(%s *)\n", FuncFPCUnit))
  5547.     return 0;
  5548.  
  5549.   return DoOutput("END. (* UNIT %s *)\n", ShortBaseNameUpper);
  5550. }
  5551.  
  5552. ULONG CreateBMAP(void)
  5553. {
  5554.   return CallFunc(TAGMODE_NORMAL, 0, FuncBMAP);
  5555. }
  5556.  
  5557. ULONG CreateLVOLib(void)
  5558. {
  5559.   ULONG a[5], i;
  5560.  
  5561.   i = strlen(ShortBaseNameUpper);
  5562.   a[0] = HUNK_UNIT; a[1] = 0; a[2] = HUNK_NAME;
  5563.   a[3] = (i + 4 + 3)>>2;
  5564.  
  5565.   DoOutputDirect(a, 16);
  5566.   DoOutputDirect(ShortBaseNameUpper, i);
  5567.   DoOutputDirect("_LVO\0\0\0", (a[3]<<2)-i);
  5568.   a[0] = HUNK_CODE; a[1] = 0; a[2] = HUNK_EXT;
  5569.   DoOutputDirect(a, 12);
  5570.   if(!CallFunc(TAGMODE_NORMAL, 0, FuncLVOLib))
  5571.     return 0;
  5572.   a[0] = 0; a[1] = HUNK_END;
  5573.   return DoOutputDirect(a, 8);
  5574. }
  5575.  
  5576. ULONG CreateVBCCInline(void)
  5577. {
  5578.   if(!clibdata)
  5579.   {
  5580.     DoError(ERR_NOPROTOTYPES_FILE, 0); return 1;
  5581.   }
  5582.  
  5583.   DoOutput("#ifndef _VBCCINLINE_%s_H\n#define _VBCCINLINE_%s_H\n",
  5584.   ShortBaseNameUpper, ShortBaseNameUpper);
  5585.  
  5586.   DoOutput("\n#ifndef EXEC_TYPES_H\n#include <exec/types.h>\n#endif\n");
  5587.  
  5588.   if(HEADER)
  5589.   {
  5590.     DoOutput("\n");
  5591.     DoOutputDirect(HEADER, headersize);
  5592.   }
  5593.  
  5594.   DoOutput("\n");
  5595.  
  5596.   if(!CallFunc(TAGMODE_NORMAL, "/%s */\n", FuncVBCCInline))
  5597.     return 0;
  5598.  
  5599.   return DoOutput("#endif /*  _VBCCINLINE_%s_H  */\n", ShortBaseNameUpper);
  5600. }
  5601.  
  5602. ULONG CreateVBCC(ULONG mode, ULONG callmode)
  5603. {
  5604.   ULONG res = 0;
  5605.  
  5606.   if(mode != 2 && mode != 3 && HEADER)
  5607.   {
  5608.     DoOutput("\n");
  5609.     DoOutputDirect(HEADER, headersize);
  5610.   }
  5611.  
  5612.   switch(mode)
  5613.   {
  5614.   case 4: res = CallFunc(callmode, 0, FuncVBCCPUPText); break;
  5615.  
  5616.   case 3: Flags |= FLAG_WOSLIBBASE; /* no break! */
  5617.   case 2: res = CallFunc(callmode, 0, FuncVBCCWOSCode); break;
  5618.  
  5619.   case 1: Flags |= FLAG_WOSLIBBASE; /* no break! */
  5620.   case 0: res = CallFunc(callmode, "\n%s", FuncVBCCWOSText); break;
  5621.   }
  5622.   return res;
  5623. }
  5624.  
  5625. ULONG CreateVBCCPUPLib(ULONG callmode)
  5626. {
  5627.   /* output header */
  5628.   DoOutput("!<arch>\n");
  5629.  
  5630.   return CallFunc(callmode, 0, FuncVBCCPUPCode);
  5631. }
  5632.  
  5633. /* ------------------------------------------------------------------ */
  5634.  
  5635. ULONG GetName(struct NameList *t, struct ShortListRoot *p, ULONG args)
  5636. {
  5637.   struct NameList *p2 = (struct NameList *) p->First;
  5638.   struct AmiPragma ap;
  5639.   ap.FuncName = t->NormName;
  5640.   ap.NumArgs = 1;
  5641.   ap.Args[0].ArgName = (args ? "args" : "tags");
  5642.   if(!MakeTagFunction(&ap))
  5643.     return 0;
  5644.  
  5645.   while(p2 && strcmp(p2->PragName, ap.TagName))
  5646.    p2 = (struct NameList *) p2->List.Next;
  5647.  
  5648.   if(!p2)
  5649.     return 0;
  5650.  
  5651.   t->Type = (args ? NTP_ARGS : NTP_TAGS);
  5652.   t->PragName = ap.TagName;
  5653.   RemoveItem(p, (struct ShortList *) p2);
  5654.  
  5655. #ifdef DEBUG_OLD
  5656.   VPrintf("GetName: name matches - %s _ %s\n", &t->NormName);
  5657. #endif
  5658.  
  5659.   return 1;
  5660. }
  5661.  
  5662. void OptimizeFDData(struct PragData *pd)
  5663. {
  5664. #ifdef DEBUG_OLD
  5665.   PutStr("OptimizeFDData\n");
  5666. #endif
  5667.  
  5668.   while(pd && !CTRL_C)
  5669.   {
  5670.     if(pd->NumNames > 1)
  5671.     {
  5672.       struct ShortListRoot n = {0,0,0}, p = {0,0,0};
  5673.       struct NameList *t;
  5674.       while(pd->Name.First)     /* sorts in AmiCall and TagCall */
  5675.       {
  5676.         t = (struct NameList *) pd->Name.First;
  5677.  
  5678.         RemoveItem(&pd->Name, (struct ShortList *) t);
  5679.         AddItem(t->PragName ? &p : &n, (struct ShortList *) t);
  5680.       }
  5681.  
  5682.       if(p.First)
  5683.       {
  5684.         t = (struct NameList *) n.First;
  5685.         while(p.First && t)
  5686.         {
  5687.           if(!GetName(t, &p, 0))
  5688.           {
  5689.             GetName(t, &p, 1);
  5690.           }
  5691.           if(t->PragName)
  5692.           {
  5693.             struct NameList *t2 = (struct NameList *) t->List.Next;
  5694.             RemoveItem(&n, (struct ShortList *)t);
  5695.             AddItem(&pd->Name, (struct ShortList *) t);
  5696.             t = t2;
  5697.           }
  5698.           else
  5699.             t = (struct NameList *) t->List.Next;
  5700.         }
  5701.         while(p.First)
  5702.         {
  5703.           if(n.First)
  5704.           {
  5705.             t = (struct NameList *) n.First;
  5706.             t->PragName = ((struct NameList *)(p.First))->PragName;
  5707.             RemoveItem(&n, (struct ShortList *) t);
  5708. #ifdef DEBUG_OLD
  5709.   VPrintf("OptimizeFDData: names together - %s _ %s\n", &t->NormName);
  5710. #endif
  5711.             t->Type = NTP_UNKNOWN;
  5712.           }
  5713.           else
  5714.           {
  5715.             ULONG i;
  5716.  
  5717.             t = (struct NameList *) p.First;
  5718.             i = strlen(t->PragName);
  5719.             t->NormName = DupString(t->PragName, i+1);
  5720.             t->NormName[i++] = 'A';
  5721.             t->NormName[i] = 0;
  5722.             t->Type = NTP_TAGS;
  5723. #ifdef DEBUG_OLD
  5724.   VPrintf("OptimizeFDData: NormName created - %s _ %s\n", &t->NormName);
  5725. #endif
  5726.           }
  5727.  
  5728.           AddItem(&pd->Name, (struct ShortList *) t);
  5729.           RemoveItem(&p, p.First);
  5730.         }
  5731.       }
  5732.  
  5733.       AddItem(&pd->Name, n.First); /* add left NormNames */
  5734.     }
  5735.     pd = (struct PragData *) pd->List.Next;
  5736.   }
  5737. }
  5738.  
  5739. ULONG MakeFD(struct PragList *pl)
  5740. {
  5741.   struct PragData *pd = (struct PragData *) pl->Data.First;
  5742.   ULONG bias;
  5743.  
  5744. #ifdef DEBUG_OLD
  5745.   PutStr("MakeFD\n");
  5746. #endif
  5747.   bias = pd->Bias;
  5748.  
  5749.   OptimizeFDData(pd);
  5750. #ifdef DEBUG_OLD
  5751.   PutStr("MakeFD: after Optimizing\n");
  5752. #endif
  5753.   DoOutput("##base _%s\n##bias %ld\n##public\n", pl->Basename, bias);
  5754.  
  5755.   while(pd && !CTRL_C && Output_Error)
  5756.   {
  5757.     struct NameList *n = (struct NameList *) pd->Name.First;
  5758.  
  5759.     if(bias != pd->Bias)
  5760.       DoOutput("##bias %ld\n", (bias = pd->Bias));
  5761.  
  5762.     while(n)
  5763.     {
  5764.       STRPTR lastpar = "last";
  5765.       ULONG i;
  5766.  
  5767.       if(n->Type == NTP_TAGS)
  5768.         lastpar = "tags";
  5769.       else if(n->Type == NTP_ARGS)
  5770.         lastpar = "args";
  5771.  
  5772.       DoOutput("%s("/*)*/,n->NormName);
  5773.       if(!pd->NumArgs)
  5774.         DoOutput(/*(*/")()\n");
  5775.       else
  5776.       {
  5777.         for(i = 0; i < pd->NumArgs-1; ++i)
  5778.           DoOutput("par%ld,",i+1);
  5779.         DoOutput(/*(*/"%s)("/*)*/, lastpar);
  5780.         for(i = 0; i < pd->NumArgs-1; ++i)
  5781.           DoOutput("%s,", RegNames[pd->ArgReg[i]]);
  5782.         DoOutput(/*(*/"%s)\n", RegNames[pd->ArgReg[i]]);
  5783.  
  5784.         if(n->Type == NTP_UNKNOWN)
  5785.         {
  5786.           ULONG i;
  5787.           for(i = 0; n->NormName[i] == n->PragName[i]; ++i)
  5788.             ;
  5789.           DoOutput("*tagcall");
  5790.           if(n->NormName[i])
  5791.             DoOutput("-%s", n->NormName+i);
  5792.           if(n->PragName[i])
  5793.             DoOutput("+%s", n->PragName+i);
  5794.  
  5795.           DoOutput("\n");
  5796.         }
  5797.       }
  5798.       if((n = (struct NameList *) n->List.Next))
  5799.         DoOutput("##bias %ld\n", pd->Bias);
  5800.       Flags |= FLAG_DONE;
  5801.     }
  5802.  
  5803.     pd = (struct PragData *)pd->List.Next; bias += BIAS_OFFSET;
  5804.   }
  5805.  
  5806.   if(CTRL_C)
  5807.     return 0;
  5808.  
  5809.   DoOutput("##end\n");
  5810.  
  5811.   return Output_Error;
  5812. }
  5813.  
  5814. ULONG AddFDData(struct ShortListRoot *pls, struct FDData *fd)
  5815. {
  5816.   struct NameList *t;
  5817.   struct PragList *pl = (struct PragList *) pls->First;
  5818.   struct PragData *pd;
  5819.  
  5820.   while(pl && strcmp(pl->Basename, fd->Basename))
  5821.     pl = (struct PragList *) pl->List.Next;
  5822.  
  5823.   if(!pl)
  5824.   {
  5825. #ifdef DEBUG_OLD
  5826.   VPrintf("AddFDData: New PragList - %s\n", &fd->Basename);
  5827. #endif
  5828.     if(!(pl = (struct PragList *) NewItem(pls)))
  5829.       return 100;
  5830.     pl->Basename = fd->Basename;
  5831.     pl->Data.Size = sizeof(struct PragData);
  5832.     AddItem(pls, (struct ShortList *) pl);
  5833.   }
  5834.  
  5835.   if((pd = (struct PragData *) pl->Data.First))
  5836.   {
  5837.     while(pd->List.Next && ((struct PragData *) pd->List.Next)->Bias
  5838.     <= fd->Bias)
  5839.       pd = (struct PragData *) pd->List.Next;
  5840.   }
  5841.  
  5842.   if(!pd || pd->Bias != fd->Bias)
  5843.   {
  5844.     struct PragData *pd2;
  5845. #ifdef DEBUG_OLD
  5846.   {
  5847.     ULONG args[2];
  5848.     args[0] = fd->Bias;
  5849.     args[1] = fd->NumArgs;
  5850.     VPrintf("AddFDData: New PragData - %ld, %ld\n", &args);
  5851.   }
  5852. #endif
  5853.     if(!(pd2 = (struct PragData *) NewItem(&pl->Data)))
  5854.       return 100;
  5855.     pd2->Bias = fd->Bias;
  5856.     CopyMem(fd->ArgReg, pd2->ArgReg, MAXREG);
  5857.     pd2->NumArgs = fd->NumArgs;
  5858.     pd2->Name.Size = sizeof(struct NameList);
  5859.     if(!pd)
  5860.       AddItem(&pl->Data, (struct ShortList *) pd2);
  5861.     else if(pd->Bias > fd->Bias) /* Insert at start */
  5862.     {
  5863.       pd2->List.Next = pl->Data.First;
  5864.       pl->Data.First = (struct ShortList *) pd2;
  5865.     }
  5866.     else /* Insert the entry */
  5867.     {
  5868.       pd2->List.Next = pd->List.Next;
  5869.       pd->List.Next = (struct ShortList *) pd2;
  5870.     }
  5871.     pd = pd2;
  5872.   }
  5873.   else
  5874.   {
  5875.     ULONG i = fd->NumArgs;
  5876.     if(fd->NumArgs != pd->NumArgs)
  5877.     {
  5878. #ifdef DEBUG_OLD
  5879.   Printf("ArgNum %ld != %ld\n", fd->NumArgs, pd->NumArgs);
  5880. #endif
  5881.       return ERR_DIFFERENT_TO_PREVIOUS;
  5882.     }
  5883.  
  5884.     while(i--)
  5885.     {
  5886.       if(fd->ArgReg[i] != pd->ArgReg[i])
  5887.       {
  5888. #ifdef DEBUG_OLD
  5889.   Printf("ArgReg %lx != %lx\n", fd->ArgReg[i], pd->ArgReg[i]);
  5890. #endif
  5891.         return ERR_DIFFERENT_TO_PREVIOUS;
  5892.       }
  5893.     }
  5894.   }
  5895.  
  5896.   t = (struct NameList *) pd->Name.First;       /* skips same names */
  5897.   while(t && strcmp(fd->Name, fd->Mode ? t->PragName : t->NormName))
  5898.     t = (struct NameList *) t->List.Next;
  5899.  
  5900.   if(t)
  5901.     return 0;
  5902.  
  5903.   if(!(t = (struct NameList *) NewItem(&pd->Name)))
  5904.     return 100;
  5905.   if(fd->Mode)
  5906.     t->PragName = fd->Name;
  5907.   else
  5908.     t->NormName = fd->Name;
  5909.   AddItem(&pd->Name, (struct ShortList *) t);
  5910.   ++(pd->NumNames);
  5911. #ifdef DEBUG_OLD
  5912.   VPrintf("AddFDData: New NameList - %s\n", &fd->Name);
  5913. #endif
  5914.   return 0;
  5915. }
  5916.  
  5917. UBYTE GetHexValue(UBYTE data)
  5918. {
  5919.   if(data >= 'a')
  5920.     return (UBYTE) (data - 'a' + 10);
  5921.   else if(data >= 'A')
  5922.     return (UBYTE) (data - 'A' + 10);
  5923.   else
  5924.     return (UBYTE) (data - '0');
  5925. }
  5926.  
  5927. UBYTE GetDoubleHexValue(UBYTE *data)
  5928. {
  5929.   return (UBYTE)((GetHexValue(*data)<<4)+GetHexValue(data[1]));
  5930. }
  5931.  
  5932. ULONG GetLibData(struct FDData *fd)
  5933. {
  5934.   ULONG i;
  5935.   fd->Name = SkipBlanks(in.pos);
  5936.   in.pos = SkipName(fd->Name); *(in.pos++) = 0;
  5937.   in.pos = SkipBlanks(in.pos);
  5938.   fd->Bias = strtoul(in.pos, 0, 16);
  5939.   in.pos = SkipName(SkipBlanks(SkipName(in.pos)));
  5940.   if((fd->NumArgs = GetHexValue(*(--in.pos))) > MAXREGNF - 2)
  5941.     return ERR_TO_MUCH_ARGUMENTS;
  5942.   --in.pos; /* skips return register */
  5943.   for(i = 0; i < fd->NumArgs; ++i)
  5944.   {
  5945.     if((fd->ArgReg[i] = GetHexValue(*(--in.pos))) > REG_A5)
  5946.       return ERR_EXPECTED_REGISTER_NAME;
  5947.   }
  5948.   return 0;
  5949. }
  5950.  
  5951. ULONG GetFlibData(struct FDData *fd)
  5952. {
  5953.   ULONG i;
  5954.   fd->Name = SkipBlanks(in.pos);
  5955.   in.pos = SkipName(fd->Name); *(in.pos++) = 0;
  5956.   in.pos = SkipBlanks(in.pos);
  5957.   fd->Bias = strtoul(in.pos, 0, 16);
  5958.   in.pos = SkipName(SkipBlanks(SkipName(in.pos))) - 2;
  5959.   if((fd->NumArgs = GetDoubleHexValue(in.pos)) > MAXREG-2)
  5960.     return ERR_TO_MUCH_ARGUMENTS;
  5961.   in.pos -= 2; /* skips return register */
  5962.   for(i = 0; i < fd->NumArgs; ++i)
  5963.   {
  5964.     in.pos -= 2;
  5965.     if((fd->ArgReg[i] = GetDoubleHexValue(in.pos)) >= MAXREG)
  5966.       return ERR_EXPECTED_REGISTER_NAME;
  5967.     else if(fd->ArgReg[i] >= REG_FP0 && (Flags & FLAG_NOFPU))
  5968.       return ERR_FLOATARG_NOT_ALLOWED;
  5969.   }
  5970.   return 0;
  5971. }
  5972.  
  5973. ULONG GetAmiData(struct FDData *fd)
  5974. {
  5975.   STRPTR endptr;
  5976.   in.pos = SkipBlanks(in.pos);
  5977.   if(*in.pos != '('/*)*/)
  5978.     return ERR_EXPECTED_OPEN_BRACKET;
  5979.   fd->Basename = ++in.pos;
  5980.   in.pos = SkipBlanks(endptr = SkipName(in.pos));
  5981.   if(*in.pos != ',')
  5982.     return ERR_EXPECTED_COMMA;
  5983.   *endptr = 0;
  5984.   in.pos = SkipBlanks(++in.pos);
  5985.   if(!strncmp(in.pos, "0x", 2))
  5986.     fd->Bias = strtoul(in.pos+2, 0, 16);
  5987.   else
  5988.     fd->Bias = strtoul(in.pos, 0, 10);
  5989.  
  5990.   in.pos = SkipBlanks(SkipName(in.pos));
  5991.   if(*in.pos != ',')
  5992.     return ERR_EXPECTED_COMMA;
  5993.   fd->Name = in.pos = SkipBlanks(++in.pos);
  5994.   in.pos = SkipBlanks(endptr = SkipName(in.pos));
  5995.   if(*in.pos != '('/*)*/)
  5996.     return ERR_EXPECTED_OPEN_BRACKET;
  5997.   *endptr = 0;
  5998.   in.pos = SkipBlanks(++in.pos);
  5999.   if(*in.pos == /*(*/')')
  6000.     return 0;
  6001.   --in.pos;
  6002.   while(*in.pos != /*(*/')')
  6003.   {
  6004.     ULONG i;
  6005.     in.pos = SkipBlanks(in.pos+1);
  6006.  
  6007.     for(i = 0; i < REG_FP0; i++)
  6008.       if(!strnicmp(RegNames[i], in.pos, 2))
  6009.         break;
  6010.     if(i == REG_FP0)
  6011.     {
  6012.       for(; i < MAXREG; i++)
  6013.         if(!strnicmp(RegNames[i], in.pos, 3))
  6014.           break;
  6015.     }
  6016.  
  6017.     if(i == MAXREG)
  6018.       return ERR_EXPECTED_REGISTER_NAME;
  6019.     else if(i >= REG_FP0 && (Flags & FLAG_NOFPU))
  6020.       return ERR_FLOATARG_NOT_ALLOWED;
  6021.  
  6022.     fd->ArgReg[fd->NumArgs] = i; ++fd->NumArgs;
  6023.  
  6024.     if(fd->NumArgs > MAXREG-2)
  6025.       return ERR_TO_MUCH_ARGUMENTS;
  6026.  
  6027.     in.pos = SkipBlanks(in.pos+(i >= REG_FP0 ? 3 : 2));
  6028.  
  6029.     if(*in.pos != ',' && *in.pos != /*(*/')')
  6030.       return ERR_EXPECTED_CLOSE_BRACKET;
  6031.   }
  6032.   in.pos = SkipBlanks(in.pos+1);
  6033.   if(*in.pos != /*(*/')')
  6034.     return ERR_EXPECTED_CLOSE_BRACKET;
  6035.   return 0;
  6036. }
  6037.  
  6038. ULONG CreateFDFile(STRPTR to)
  6039. {
  6040.   struct ShortListRoot pl = {0, 0, sizeof(struct PragList)};
  6041.   ULONG linenum, err = 0, skip;
  6042.  
  6043.   for(linenum = 1; !CTRL_C && in.pos < in.buf + in.size; ++linenum)
  6044.   {
  6045.     in.pos = SkipBlanks(in.pos);
  6046.     if(!strncmp("#pragma", in.pos, 7))
  6047.     {
  6048.       struct FDData fd;
  6049.  
  6050.       skip = 0;
  6051.       memset(&fd, 0, sizeof(struct FDData));
  6052.  
  6053.       in.pos = SkipBlanks(in.pos+7);
  6054.       if(!strncmp("tagcall", in.pos, 7))
  6055.       {
  6056.         fd.Mode = 1;
  6057.         in.pos = SkipBlanks(in.pos+7);
  6058.         if(*in.pos == '(' /*)*/)                /* Storm method */
  6059.           err = GetAmiData(&fd);
  6060.         else                                    /* SAS method */
  6061.         {
  6062.           fd.Basename = in.pos;
  6063.           in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  6064.           err = GetLibData(&fd);
  6065.         }
  6066.       }
  6067.       else if(!strncmp("amicall", in.pos, 7))   /* Storm method */
  6068.       {
  6069.         in.pos += 7;
  6070.         err = GetAmiData(&fd);
  6071.       }
  6072.       else if(!strncmp("libcall", in.pos, 7))   /* SAS method */
  6073.       {
  6074.         fd.Basename = SkipBlanks(in.pos+7);
  6075.         in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  6076.         err = GetLibData(&fd);
  6077.       }
  6078.       else if(!strncmp("flibcall", in.pos, 8))  /* SAS method */
  6079.       {
  6080.         fd.Basename = SkipBlanks(in.pos+8);
  6081.         in.pos = SkipName(fd.Basename); *(in.pos++) = 0;
  6082.         err = GetFlibData(&fd);
  6083.       }
  6084.       else if(!strncmp("syscall", in.pos, 7))   /* SAS method */
  6085.       {
  6086.         fd.Basename = "SysBase";
  6087.         err = GetLibData(&fd);
  6088.       }
  6089.       else
  6090.         skip = 1;
  6091.  
  6092.       if(err)
  6093.         DoError(err, linenum);
  6094.       else if(skip)
  6095.         ;
  6096.       else if((err = AddFDData(&pl, &fd)))
  6097.       {
  6098.         if(err != 100)
  6099.           DoError(err, linenum);
  6100.         return 0;
  6101.       }
  6102.     }
  6103.     while(*(in.pos++))  /* jumps to first char of next line */
  6104.       ;
  6105.   }
  6106.  
  6107.   if(pl.First && !CTRL_C)
  6108.   {
  6109.     struct PragList *p = (struct PragList *) pl.First;
  6110.     if(!p->List.Next)
  6111.     {
  6112.       if(!to)
  6113.       {
  6114.         STRPTR text;
  6115.         ULONG i;
  6116.  
  6117.         if(ShortBaseName)
  6118.         {
  6119.           text = ShortBaseName; i = strlen(text);
  6120.         }
  6121.         else
  6122.         {
  6123.           text = p->Basename; i = strlen(text)-4;
  6124.         }
  6125.  
  6126.         to = DupString(text, i + sizeof(FDFILEEXTENSION) - 1);
  6127.         CopyMem(FDFILEEXTENSION, to+i, sizeof(FDFILEEXTENSION));
  6128.       }
  6129.       if(!(out.file = Open(to, MODE_NEWFILE)))
  6130.         return 0;
  6131.       
  6132.       err = MakeFD(p);
  6133.       CloseDest(to);
  6134.       if(!err)
  6135.         return 0;
  6136.     }
  6137.     else
  6138.     {
  6139.       while(p)
  6140.       {
  6141.         ULONG i;
  6142.         i = strlen(p->Basename) - 4;
  6143.         to = DupString(p->Basename, i + sizeof(FDFILEEXTENSION) - 1);
  6144.         CopyMem(FDFILEEXTENSION, to+i, sizeof(FDFILEEXTENSION));
  6145.         if(!(out.file = Open(to, MODE_NEWFILE)))
  6146.           return 0;
  6147.         i = MakeFD(p);
  6148.         CloseDest(to);
  6149.         if(!i)
  6150.           return 0;
  6151.         p = (struct PragList *) p->List.Next;
  6152.       }
  6153.     }
  6154.   }
  6155.  
  6156.   if(CTRL_C)
  6157.     DoError(ERR_USER_ABORT, 0);
  6158.  
  6159.   return 1;
  6160. }
  6161.  
  6162. const STRPTR helptext =
  6163. "INFILE:  the input file which should be used\n"
  6164. "SPECIAL: 1 - Aztec compiler (xxx_lib.h,     MODE 2, AMICALL)\n"
  6165. "\t 2 - DICE compiler  (xxx_pragmas.h, MODE 3, LIBCALL)\n"
  6166. "\t 3 - SAS compiler   (xxx_pragmas.h, MODE 3, LIBCALL,LIBTAGS)\n"
  6167. "\t 4 - MAXON compiler (xxx_lib.h,     MODE 1, AMICALL)\n"
  6168. "\t 5 - STORM compiler (xxx_lib.h,     MODE 1, AMITAGS,AMICALL)\n"
  6169. "\t 6 - all compilers [default]\n"
  6170. "\t 7 - all compilers with pragma to inline redirect for GCC\n"
  6171. "\t 8 - pragma to inline redirect for GCC\n"
  6172. "\t10 - stub-functions for C - C text\n"
  6173. "\t11 - stub-functions for C - assembler text\n"
  6174. "\t12 - stub-functions for C - link library\n"
  6175. "\t13 - defines and link library for local library base (register call)\n"
  6176. "\t14 - defines and link library for local library base (stack call)\n"
  6177. "\t15 - stub-functions for Pascal - assembler text\n"
  6178. "\t16 - stub-functions for Pascal - link library\n"
  6179. "\t17 - BMAP file for AmigaBASIC and MaxonBASIC\n"
  6180. "\t20 - assembler lvo _lvo.i file\n"
  6181. "\t21 - assembler lvo _lib.i file\n"
  6182. "\t22 - assembler lvo _lvo.i file no XDEF\n"
  6183. "\t23 - assembler lvo _lib.i file no XDEF\n"
  6184. "\t24 - assembler lvo link library\n"
  6185. "\t30 - proto file with pragma/..._lib.h call\n"
  6186. "\t31 - proto file with pragma/..._pragmas.h call\n"
  6187. "\t32 - proto file with pragmas/..._lib.h call\n"
  6188. "\t33 - proto file with pragmas/..._pragmas.h call\n"
  6189. "\t34 - proto file with local/..._loc.h call\n"
  6190. "\t35 - proto file for all compilers\n"
  6191. "\t36 - proto file for GNU-C compiler only\n"
  6192. "\t37 - proto file without lib definitions\n"
  6193. "\t40 - GCC inline file (preprocessor based)\n"
  6194. "\t41 - GCC inline file (old type - inline based)\n"
  6195. "\t42 - GCC inline file (library stubs)\n"
  6196. "\t50 - GCC inline files for PowerUP (preprocessor based)\n"
  6197. "\t51 - GCC inline files for PowerUP (old type - inline based)\n"
  6198. "\t52 - GCC inline files for PowerUP (library stubs)\n"
  6199. "\t53 - SAS-C include file for PowerUP\n"
  6200. "\t54 - Proto file for PowerUP\n"
  6201. "\t60 - FPC pascal unit text\n"
  6202. "\t70 - VBCC inline files\n"
  6203. "\t71 - VBCC WOS stub-functions - assembler text\n"
  6204. "\t72 - VBCC WOS stub-functions - assembler text (libbase)\n"
  6205. "\t73 - VBCC WOS stub-functions - link library\n"
  6206. "\t74 - VBCC WOS stub-functions - link library (libbase)\n"
  6207. "\t75 - VBCC PowerUP stub-functions - assembler text\n"
  6208. "\t76 - VBCC PowerUP stub-functions - link library\n"
  6209. "       200 - FD file (source is a pragma file!)\n"
  6210. "MODE:\t SPECIAL 1-7,AMICALL,LIBCALL,AMITAGS,LIBTAGS:\n"
  6211. "\t 1 - _INCLUDE_PRAGMA_..._LIB_H definition method [default]\n"
  6212. "\t 2 - _PRAGMAS_..._LIB_H definition method\n"
  6213. "\t 3 - _PRAGMAS_..._PRAGMAS_H definition method\n"
  6214. "\t 4 - no definition\n"
  6215. "\t SPECIAL 11-14,40-42,50-53,71-76:\n"
  6216. "\t 1 - all functions, normal interface\n"
  6217. "\t 2 - only tag-functions, tagcall interface\n"
  6218. "\t 3 - all functions, normal and tagcall interface [default]\n"
  6219. "TO:\t the destination directory (self creation of filename) or\n"
  6220. "\t the destination file\n"
  6221. "CLIB:    name of the prototypes file in clib directory\n"
  6222. "HEADER:  inserts given file into header of created file (\"\" is scan)\n"
  6223. "The following four need a string as an argument. This string is used to set\n"
  6224. "a #if<given string> before the set method.\n"
  6225. "AMICALL: creates amicall pragmas\n"
  6226. "LIBCALL: creates libcall pragmas\n"
  6227. "AMITAGS: creates tagcall pragmas (amicall like method (StormC++))\n"
  6228. "LIBTAGS: creates tagcall pragmas (libcall like method (SAS C))\n"
  6229. "Switches:\n"
  6230. "COMMENT:    copy comments found in FD file\n"
  6231. "EXTERNC:    add a #ifdef __cplusplus ... statement to pragma file\n"
  6232. "FPUONLY:    work only with functions using FPU register arguments\n"
  6233. "NEWSYNTAX:  uses new Motorola syntax for asm files\n"
  6234. "NOFPU:      disable usage of FPU register arguments\n"
  6235. "NOPPC:      disable usage of PPC-ABI functions\n"
  6236. "NOSYMBOL:   prevents creation of SYMBOL hunks for link libraries\n"
  6237. "OPT040:     optimize for 68040, do not use MOVEM for stubs\n"
  6238. "PPCONLY:    only use PPC-ABI functions\n"
  6239. "PRIVATE:    includes private declared functions\n"
  6240. "SECTION:    add section statements to asm texts\n"
  6241. "SMALLDATA:  generate small data link libraries or assembler text\n"
  6242. "SORTED:     sort generated files by name and not by bias value\n"
  6243. "STORMFD:    converts FD files of strange StormC++ format\n"
  6244. "USESYSCALL: uses syscall pragma instead of libcall SysBase\n";
  6245.  
  6246. void main(void)
  6247. {
  6248.   ULONG mode = 0, pragmode = PRAGMODE_PRAGLIB, callmode = TAGMODE_BOTH;
  6249.   ULONG spec = 0; /* for default setting I need a ULONG var to get a pointer */
  6250.   UBYTE filename[255]; /* needed for filename */
  6251.   struct Args args;
  6252.   STRPTR clibbuf = 0;
  6253.   ULONG clibsize = 0;
  6254.  
  6255. #ifdef __SASC   /* with __MAXON__ this is done automatic by my StartUp */
  6256.   TestOS;
  6257. #endif
  6258.  
  6259.   memset(&args, 0, sizeof(struct Args)); /* initialize */
  6260.   args.SPECIAL = &spec;
  6261.  
  6262.   if(!(rda = (struct RDArgs *) AllocDosObject(DOS_RDARGS, 0)))
  6263.     End(RETURN_FAIL);
  6264.   rda->RDA_ExtHelp = helptext;
  6265.   if(!ReadArgs(PARAM, (LONG *) &args, rda))
  6266.     End(RETURN_FAIL);
  6267.  
  6268.   if(!(in.file = Open(args.INFILE, MODE_OLDFILE)))
  6269.   {
  6270.     sprintf(filename, "%s" FDFILEEXTENSION, args.INFILE);
  6271.     if(*args.SPECIAL == 200 || !(in.file = Open(filename, MODE_OLDFILE)))
  6272.     {
  6273.       DoError(ERR_OPEN_FILE, 0, args.INFILE);
  6274.       End(RETURN_FAIL);
  6275.     }
  6276.     else
  6277.       args.INFILE = filename;
  6278.   }
  6279.  
  6280.   VPrintf("SourceFile: %s\n", &args.INFILE);
  6281.  
  6282.   /* OS39 and up may use AllocPooled instead of normal AllocMem. If this
  6283.      fails, we use normal method */
  6284.   if(SysBase->LibNode.lib_Version >= 39)
  6285.     mempool = CreatePool(MEMF_ANY|MEMF_CLEAR,10240,2048);
  6286.  
  6287.   if(!(fib = (struct FileInfoBlock *) AllocDosObject(DOS_FIB, 0)) ||
  6288.   !ExamineFH(in.file, fib) ||
  6289.   !(in.buf = in.pos = AllocListMem((in.size = fib->fib_Size)+1)) ||
  6290.   Read(in.file, in.buf, in.size) != in.size ||
  6291.   !(out.buf = out.pos = AllocListMem(out.size)) ||
  6292.   !(tempbuf = AllocListMem(TEMPSIZE)))
  6293.     End(RETURN_FAIL);
  6294.   else
  6295.   {
  6296.     STRPTR ptr = FilePart(args.INFILE);
  6297.     LONG len = strlen(ptr) - sizeof(FDFILEEXTENSION) + 1;
  6298.     if(len >= 0 && !stricmp(ptr+len, FDFILEEXTENSION))
  6299.       ShortBaseName = DupString(ptr, len);
  6300.   }
  6301.  
  6302.   MakeLines(in.pos, in.size);
  6303.  
  6304.   if(args.EXTERNC)      Flags ^= FLAG_EXTERNC;
  6305.   if(args.STORMFD)      Flags ^= FLAG_STORMFD;
  6306.   if(args.PRIVATE)      Flags ^= FLAG_PRIVATE;
  6307.   if(args.NEWSYNTAX)    Flags ^= FLAG_NEWSYNTAX;
  6308.   if(args.SMALLDATA)    Flags ^= FLAG_SMALLDATA;
  6309.   if(args.USESYSCALL)   Flags ^= FLAG_SYSCALL;
  6310.   if(args.OPT040)       Flags ^= FLAG_NOMOVEM;
  6311.   if(args.NOFPU)        Flags ^= FLAG_NOFPU;
  6312.   if(args.FPUONLY)      Flags ^= FLAG_FPUONLY;
  6313.   if(args.NOPPC)        Flags ^= FLAG_NOPPC;
  6314.   if(args.NOSYMBOL)    Flags ^= FLAG_NOSYMBOL;
  6315.   if(args.PPCONLY)      Flags ^= FLAG_PPCONLY;
  6316.   if(args.SECTION)    Flags ^= FLAG_ASMSECTION;
  6317.   if(args.COMMENT && !args.SORTED)
  6318.     Flags ^= FLAG_DOCOMMENT;
  6319.  
  6320.   if(args.TO)
  6321.   {
  6322.     if((lock = Lock(args.TO, SHARED_LOCK)) && Examine(lock, fib) &&
  6323.     fib->fib_DirEntryType > 0)
  6324.       args.TO = 0;
  6325.     else if(lock)
  6326.     {
  6327.       UnLock(lock);
  6328.       lock = 0;
  6329.     }
  6330.   }
  6331.  
  6332.   if(*args.SPECIAL == 200)
  6333.   {
  6334.     STRPTR ptr = FilePart(args.INFILE), ptr2;
  6335.  
  6336.     for(ptr2 = ptr; *ptr2 && *ptr2 != '_' && *ptr2 != '.'; ++ptr2)
  6337.       ;
  6338.     if(ptr2 != ptr)
  6339.     {
  6340.       ShortBaseName = ptr;
  6341.       *ptr2 = '\0';
  6342.     }
  6343.     if(lock)
  6344.       oldfh = CurrentDir(lock);
  6345.     if(!CreateFDFile(args.TO))
  6346.       End(RETURN_FAIL);
  6347.     End(RETURN_OK);
  6348.   }
  6349.  
  6350.   Close(in.file);
  6351.   if((in.file = Open(EXTTYPESFILE, MODE_OLDFILE)) ||
  6352.   (in.file = Open(EXTTYPESFILE2, MODE_OLDFILE)))
  6353.   {
  6354.     STRPTR ptr;
  6355.  
  6356.     if(ExamineFH(in.file, fib) && (ptr = AllocListMem(fib->fib_Size)) &&
  6357.     Read(in.file, ptr, fib->fib_Size) == fib->fib_Size)
  6358.     {
  6359.       ULONG i;
  6360.       if((i = ScanTypes(ptr, fib->fib_Size)) > 0)
  6361.         DoError(ERR_WRONG_TYPES_LINE, i);
  6362.       if(i)
  6363.         End(RETURN_FAIL);
  6364.     }
  6365.     else
  6366.       End(RETURN_FAIL);
  6367.  
  6368.     Close(in.file); in.file = 0;
  6369.   }
  6370.  
  6371.   if(args.CLIB)
  6372.   {
  6373.  
  6374.     if(!(in.file = Open(args.CLIB, MODE_OLDFILE)))
  6375.     {
  6376.       sprintf(filename, "%s_protos.h", args.CLIB);
  6377.       if(!(in.file = Open(filename, MODE_OLDFILE)))
  6378.       {
  6379.         DoError(ERR_OPEN_FILE, 0, args.CLIB);
  6380.         End(RETURN_FAIL);
  6381.       }
  6382.     }
  6383.     if(!ExamineFH(in.file, fib) ||
  6384.     !(clibbuf = AllocListMem((clibsize = fib->fib_Size + 1))) ||
  6385.     Read(in.file, clibbuf, fib->fib_Size) != fib->fib_Size)
  6386.       End(RETURN_FAIL);
  6387.     ScanClibFile(clibbuf, clibbuf+fib->fib_Size);
  6388.     Close(in.file); in.file = 0;
  6389.   }
  6390.  
  6391.   if(lock)
  6392.     oldfh = CurrentDir(lock);
  6393.  
  6394.   if(!ScanFDFile())
  6395.     End(RETURN_FAIL);
  6396.  
  6397.   if(args.SORTED)
  6398.     SortFDList();
  6399.  
  6400.   if(!ShortBaseName)
  6401.   {
  6402.     DoError(ERR_MISSING_SHORTBASENAME, 0); End(RETURN_FAIL);
  6403.   }
  6404.   else if((ShortBaseNameUpper = DupString(ShortBaseName,
  6405.   strlen(ShortBaseName))))
  6406.   {
  6407.     STRPTR a = ShortBaseNameUpper;
  6408.     while((*a = toupper(*a))) /* Convert to uppercase */
  6409.       a++;
  6410.   }
  6411.   else
  6412.     End(RETURN_FAIL);
  6413.  
  6414.   if(*args.SPECIAL < 10) /* the pragma area is up to 9 */
  6415.   {
  6416.     STRPTR amicall = 0, libcall = 0, amitags = 0, libtags = 0;
  6417.  
  6418.     mode = MODUS_PRAGMA;
  6419.     sprintf(filename, "%s_lib.h", ShortBaseName);
  6420.  
  6421.     if(!args.LIBTAGS && !args.AMITAGS && !args.LIBCALL && !args.AMICALL &&
  6422.     !*args.SPECIAL)
  6423.       *args.SPECIAL = 6; /* default mode */
  6424.  
  6425.     switch(*args.SPECIAL)
  6426.     {
  6427.       case 0: break;
  6428.       case 1: pragmode = PRAGMODE_PRAGSLIB; amicall = ""; break;
  6429.       case 2: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  6430.               pragmode = PRAGMODE_PRAGSPRAGS; libcall = ""; break;
  6431.       case 3: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  6432.               pragmode = PRAGMODE_PRAGSPRAGS; libcall = "";
  6433.               libtags = "def " TEXT_SAS_60; break;
  6434.       case 4: amicall = ""; break;
  6435.       case 5: amicall = amitags = ""; break;
  6436.       case 7: Flags |= FLAG_GNUPRAG; /* no break ! */
  6437.       case 6: amicall = " defined(" TEXT_AZTEC ") || defined("
  6438.               TEXT_MAXON ") || defined(" TEXT_STORM ")";
  6439.               libcall = " defined(" TEXT_DICE ") || defined(" TEXT_SAS ")";
  6440.               libtags = "def " TEXT_SAS_60; amitags ="def " TEXT_STORM; break;
  6441.       case 8: sprintf(filename, "%s_pragmas.h", ShortBaseName);
  6442.               Flags |= FLAG_GNUPRAG; pragmode = PRAGMODE_PRAGSPRAGS; break;
  6443.       default: mode = MODUS_ERROR; break;
  6444.     }
  6445.  
  6446.     if(!args.AMICALL)   args.AMICALL = amicall;
  6447.     if(!args.LIBCALL)   args.LIBCALL = libcall;
  6448.     if(!args.AMITAGS)   args.AMITAGS = amitags;
  6449.     if(!args.LIBTAGS)   args.LIBTAGS = libtags;
  6450.  
  6451.     if(args.MODE && *args.MODE > 0 && *args.MODE < 5)
  6452.       pragmode = *args.MODE;
  6453.   }
  6454.   else if(*args.SPECIAL < 20) /* the misc area is up to 19 */
  6455.   {
  6456.     if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
  6457.       callmode = *args.MODE - 1;
  6458.     switch(*args.SPECIAL)
  6459.     {
  6460.     case 10: mode = MODUS_CSTUB;
  6461.       sprintf(filename, "%s_cstub.h", ShortBaseName); break;
  6462.     case 11: mode = MODUS_STUBTEXT;
  6463.       sprintf(filename, "%s_stub.s", ShortBaseName); break;
  6464.     case 12: mode = MODUS_STUBCODE;
  6465.       sprintf(filename, "%s.lib", ShortBaseName); break;
  6466.     case 13: Flags |= FLAG_LOCALREG; /* no break ! */
  6467.     case 14: mode = MODUS_LOCALDATA;
  6468.       sprintf(filename, "%s_loc.h", ShortBaseName); args.TO = 0; break;
  6469.     case 15: mode = MODUS_STUBTEXT; callmode = TAGMODE_NORMAL;
  6470.       Flags ^= FLAG_PASCAL;
  6471.       sprintf(filename, "%s_stub.s", ShortBaseName); break;
  6472.     case 16: mode = MODUS_STUBCODE; callmode = TAGMODE_NORMAL;
  6473.       Flags ^= FLAG_PASCAL;
  6474.       sprintf(filename, "%s.lib", ShortBaseName); break;
  6475.     case 17: mode = MODUS_BMAP; callmode = TAGMODE_NORMAL;
  6476.       sprintf(filename, "%s.bmap", ShortBaseName); break;
  6477.     default: mode = MODUS_ERROR; break;
  6478.     }
  6479.   }
  6480.   else if(*args.SPECIAL < 30) /* the lvo area is up to 29 */
  6481.   {
  6482.     switch(*args.SPECIAL)
  6483.     {
  6484.     case 20: case 22: mode = MODUS_LVO+*args.SPECIAL-20;
  6485.       sprintf(filename, "%s_lvo.i", ShortBaseName); break;
  6486.     case 21: case 23: mode = MODUS_LVO+*args.SPECIAL-20;
  6487.       sprintf(filename, "%s_lib.i", ShortBaseName); break;
  6488.     case 24: mode = MODUS_LVOLIB;
  6489.       sprintf(filename, "%s.lib", ShortBaseName); break;
  6490.     default: mode = MODUS_ERROR; break;
  6491.     }
  6492.   }
  6493.   else if(*args.SPECIAL < 40) /* the proto area is up to 39 */
  6494.   {
  6495.     if(*args.SPECIAL < 38)
  6496.     {
  6497.       mode = MODUS_PROTO+*args.SPECIAL-30+1;
  6498.       sprintf(filename, "%s.h", ShortBaseName);
  6499.     }
  6500.     else
  6501.       mode = MODUS_ERROR;
  6502.   }
  6503.   else if(*args.SPECIAL < 50) /* the inline area is up to 49 */
  6504.   {
  6505.     if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
  6506.       callmode = *args.MODE - 1;
  6507.  
  6508.     switch(*args.SPECIAL)
  6509.     {
  6510.     case 40: case 41: case 42: mode = MODUS_INLINE+*args.SPECIAL-40;
  6511.       sprintf(filename, "%s.h", ShortBaseName); break;
  6512.     default: mode = MODUS_ERROR; break;
  6513.     }
  6514.   }
  6515.   else if(*args.SPECIAL < 60) /* the PowerUP area is up to 59 */
  6516.   {
  6517.     if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
  6518.       callmode = *args.MODE - 1;
  6519.  
  6520.     switch(*args.SPECIAL)
  6521.     {
  6522.     case 50: case 51: case 52: mode = MODUS_INLINE+*args.SPECIAL-50;
  6523.       sprintf(filename, "%s.h", ShortBaseName); Flags |= FLAG_POWERUP;
  6524.       break;
  6525.     case 53:
  6526.       sprintf(filename, "%s_pragmas.h", ShortBaseName);
  6527.       mode = MODUS_SASPOWER; break;
  6528.     case 54:
  6529.       sprintf(filename, "%s.h", ShortBaseName);
  6530.       mode = MODUS_PROTOPOWER; break;
  6531.     default: mode = MODUS_ERROR; break;
  6532.     }
  6533.   }
  6534.   else if(*args.SPECIAL < 70) /* the PASCAL stuff */
  6535.   {
  6536.     if(*args.SPECIAL == 60)
  6537.     {
  6538.       mode = MODUS_PASCAL;
  6539.       sprintf(filename, "%s.pas", ShortBaseName);
  6540.     }
  6541.     else
  6542.       mode = MODUS_ERROR;
  6543.   }
  6544.   else if(*args.SPECIAL < 80) /* the VBCC stuff */
  6545.   {
  6546.     if(args.MODE && *args.MODE > 0 && *args.MODE < 4)
  6547.       callmode = *args.MODE - 1;
  6548.  
  6549.     switch(*args.SPECIAL)
  6550.     {
  6551.     case 70: mode = MODUS_VBCCINLINE;
  6552.       sprintf(filename, "%s.h", ShortBaseName); break;
  6553.     case 71: case 72: case 75:
  6554.       mode = MODUS_VBCC+*args.SPECIAL-71;
  6555.       sprintf(filename, "%s_stub.s", ShortBaseName); break;
  6556.     case 73: case 74:
  6557.       mode = MODUS_VBCC+*args.SPECIAL-71;
  6558.       sprintf(filename, "%s.lib", ShortBaseName); break;
  6559.     case 76:
  6560.       mode = MODUS_VBCCPUPLIB;
  6561.       sprintf(filename, "lib%s.a", ShortBaseName); break;
  6562.     default: mode = MODUS_ERROR; break;
  6563.     }
  6564.   }
  6565.  
  6566.   if(!mode)
  6567.   {
  6568.     SetIoErr(ERROR_REQUIRED_ARG_MISSING);
  6569.     End(RETURN_FAIL);
  6570.   }
  6571.   else if(mode == MODUS_ERROR)
  6572.   {
  6573.     SetIoErr(ERROR_TOO_MANY_ARGS);
  6574.     End(RETURN_FAIL);
  6575.   }
  6576.  
  6577.   /* These modes need BaseName always. */
  6578.   if(!BaseName && (mode == MODUS_PRAGMA || mode == MODUS_STUBTEXT ||
  6579.   mode == MODUS_STUBCODE))
  6580.   {
  6581.     DoError(ERR_MISSING_BASENAME, 0); End(RETURN_FAIL);
  6582.   }
  6583.  
  6584.   if(!args.TO)
  6585.     args.TO = filename;
  6586.  
  6587.   if(args.HEADER)
  6588.   {
  6589.     if(!*args.HEADER || (!args.HEADER[1] && *args.HEADER=='@'))
  6590.       args.HEADER = args.TO;
  6591.     if(!(in.file = Open(args.HEADER, MODE_OLDFILE)) ||
  6592.     !ExamineFH(in.file, fib) ||
  6593.     !(HEADER = AllocListMem((headersize = fib->fib_Size)+1)) ||
  6594.     Read(in.file, HEADER, headersize) != headersize)
  6595.       End(RETURN_FAIL);
  6596.     if(args.HEADER == args.TO)
  6597.       FindHeader();
  6598.     Close(in.file);
  6599.     in.file = 0;
  6600.   }
  6601.  
  6602.   if(!(out.file = Open(args.TO, MODE_NEWFILE)))
  6603.     End(RETURN_FAIL);
  6604.  
  6605.   SetIoErr(0);
  6606.  
  6607.   /* from here mode is used as return result */
  6608.   if(mode >= MODUS_VBCC)
  6609.     mode = CreateVBCC(mode-MODUS_VBCC, callmode);
  6610.   else if(mode >= MODUS_INLINE)
  6611.     mode = CreateInline(mode-MODUS_INLINE, callmode);
  6612.   else if(mode >= MODUS_PROTO)
  6613.     mode = CreateProtoFile(mode-MODUS_PROTO);
  6614.   else if(mode >= MODUS_LVO)
  6615.     mode = CreateLVOFile(mode-MODUS_LVO+1);
  6616.   else if(mode == MODUS_LVOLIB)
  6617.     mode = CreateLVOLib();
  6618.   else if(mode == MODUS_VBCCPUPLIB)
  6619.     mode = CreateVBCCPUPLib(callmode);
  6620.   else if(mode == MODUS_VBCCINLINE)
  6621.     mode = CreateVBCCInline();
  6622.   else if(mode == MODUS_PASCAL)
  6623.     mode = CreateFPCUnit();
  6624.   else if(mode == MODUS_BMAP)
  6625.     mode = CreateBMAP();
  6626.   else if(mode == MODUS_PROTOPOWER)
  6627.     mode = CreateProtoPowerUP();
  6628.   else if(mode == MODUS_SASPOWER)
  6629.     mode = CreateSASPowerUP(callmode);
  6630.   else if(mode == MODUS_CSTUB)
  6631.     mode = CreateCSTUBSFile();
  6632.   else if(mode == MODUS_PRAGMA)
  6633.     mode = CreatePragmaFile(args.AMICALL, args.LIBCALL, args.AMITAGS, args.LIBTAGS, pragmode);
  6634.   else if(mode == MODUS_LOCALDATA)
  6635.     mode = CreateLocalData(args.TO, callmode, clibbuf, clibsize);
  6636.   else if(mode)             /* MODUS_STUBTEXT starts with 1 */
  6637.     mode = CreateAsmStubs(mode, callmode);
  6638.  
  6639.   CloseDest(args.TO);
  6640.  
  6641.   if(CTRL_C)
  6642.     DoError(ERR_USER_ABORT, 0);
  6643.   else if(!mode)
  6644.   {
  6645.     DoError(Output_Error ? ERR_UNKNOWN_ERROR : ERR_WRITING_FILE, 0);
  6646.     End(RETURN_FAIL);
  6647.   }
  6648.  
  6649.   End(RETURN_OK);
  6650. }
  6651.  
  6652. void End(ULONG err)
  6653. {
  6654.   if(err && !(Flags & FLAG_DIDERROR))
  6655.     PrintFault(IoErr(), 0);
  6656.  
  6657.   if(fib)
  6658.     FreeDosObject(DOS_FIB, fib);
  6659.   if(in.file)
  6660.     Close(in.file);
  6661.   if(lock)
  6662.   {
  6663.     CurrentDir(oldfh);
  6664.     UnLock(lock);
  6665.   }
  6666.   if(mempool) /* free allocated pool and all entries */
  6667.     DeletePool(mempool);
  6668.   if(remember) /* free remember list */
  6669.   {
  6670.     struct RememberMem *r, *s;
  6671.  
  6672.     r = remember;
  6673.     while(r)
  6674.     {
  6675.       s = r;
  6676.       r = r->rm_Next;
  6677.  
  6678.       FreeMem(s, s->rm_Size);
  6679.     }
  6680.   }
  6681.   if(rda)
  6682.   {
  6683.     FreeArgs(rda);
  6684.     FreeDosObject(DOS_RDARGS, rda);
  6685.   }
  6686.   exit(err);
  6687. }
  6688.